我喃喃自語說︰我做了一個夢。在那夢中我做了一個夢,我喃喃自語說︰我做了一個夢。宛如我置身『鏡廊』一面『鏡子』前,我見着了『鏡裡』的我置身『鏡廊』一面『鏡子』前,… 。
俄羅斯娃哇是『有趣的』事物,雖然只有『有限』的幾個『迭套』,它卻是『象徵』一個『不思議』的『奧秘』。其實『遞迴』Recursion 與『疊代』 Iteration 兩個概念,彼此間有著很深刻的『聯繫』。
為什麼數學上常常要用『遞迴定義』的呢?假使你出於『好玩』,想『定義』一個『數列』,那麼有什麼『簡單』的辦法的呢?
有人說︰這很簡單啊!就給一個 『公式』Formula 就好了,就好比講這個數列是
。
有人問︰萬一你不知道『那個公式』呢?還是說如果『公式不存在』這樣子就根本『沒辦法』去定義『數列』的呢?
有人答︰『可以』的啊!比方說假使你『知道』
一、 的『值』
二、曉得如何從 『計算』出 的『值』,這樣就算是不知道 是能不能夠表達,一樣可以『定義』這個『數列』的啊!
據說義大利的數學家李奧納多‧費波那契 Leonardo Fibonacci 描述各代『兔子生育』總數目時得到這個數列︰
因此 ,所以可以逐步的得到『費波那契數列』。當然可以求解那一個『差分方程式』得到
。
然而並非所有可以『遞迴定義』的數列,都能有『公式解』,或者說還沒將它『算出來』。所以能這樣從幾個『初始資料』和一個『遞迴關係』來定義東西的方式,自然有它的好處的了。
一般人們用程式計算『數列』 的『級數和』
,很自然的會用『疊代』的想法,可以表達為
,此處『:=』表示變數『賦值』,逐項累加到所需要的 次。這或許是大部分的程式語言都有『FOR LOOP』的原因。但是遇到了像『河內塔』這一類問題,由於那個 本身就先需要計算出來,況且還和 有關,這時想寫個『疊代法』程式就很困難的了。所以『方法選擇』應當針對『問題狀況』,難有『萬能之法』的啊!
為了談談『疊代』與『遞迴』之間的『聯繫』,我們先舉一個如何用『遞迴』來寫『加法』例子︰
IF y is 0 THEN x
ELSE addr (SUCC x) (PRED y)
將之翻譯成『Y組合子』用的『 λ表達式』︰
假使我們知道 ,那麼可以『手動』改寫『addr』為︰
IF y is 0 THEN x
ELSE (
IF ((PRED y) is 0) THEN (SUCC x)
ELSE (
IF (PRED (PRED y) is 0) THEN SUCC(SUCC x)
ELSE (0) ※FAIL
)
並且翻譯成 Lambda Calculator 寫法
\x.\y. IFTHENELSE (ISZERO y) (x) (IFTHENELSE (ISZERO (PRED y)) (SUCC x) (IFTHENELSE (ISZERO (PRED (PRED y))) (SUCC (SUCC x) ) (0) ))
也就是說有限的遞迴通常可以手動的『複製遞迴計算』,自己賦與遞迴中所需要的『呼叫參數值』,改寫成『非遞迴』的『長版本程式』。這個程式中有許多的『自我相似』的『程式碼』,彷彿是個『俄羅斯娃娃』的『構造』一般!如果將它翻譯成『疊代』的程式,經常會作『概念改寫』︰將 減一,且將 加一,直到 為止。它雖然經常能夠得到『短版本程式』,但是兩者間的『概念聯繫』是很明晰的啊!!
所以當我們還不清楚可能的『計算步驟』時『遞迴』有『優勢』,如果有對等的『疊代』程式通常『執行速度』會比較『快』,因此許多程式語言也有使用『中止條件』的『WHILE LOOP』之建構。萬一『中止條件』在有限時間裡始終達不到,或許將會陷入『無窮循環』,這時兩者狀況是相似的。但是也不要以為『無窮循環』就一定是『不好的』,有時候它正是所要的『目的』,就像『CPU』開機後就一直運作執行一樣。
為什麼 λ表達式無法『直接指涉』自身的呢?因為在『純 λ語言』裡你無法『定義』標示符號,所以當表達成
,這只是為了方便的說法,無法如設想的『化約』表達式中 是『定義』的『引用』,它在『化約』時只會被當成一個叫做 的『變元』,於是根本就達不成『遞迴』之目的了。