2016-08-05 51 views
3

讓我們考慮一個階乘函數的一個簡單的例子,寫的僞像CPS式(枚舉的中間結果&排序被省略了,因爲會很吵):調用延續VS函數調用

(def (fact n k) (if (eq? n 0) (k 1) (fact (- n 1) (\result (k (* n result)))))) 

調用延續(k 1)(即「返回」一個值)在技術上與「正常」函數調用不同,就像在else分支中一樣嗎?我想到的一件事是,在這種情況下,延續是唯一沒有其他延續的論點:)

另外,你能說這個計算類似於DFS樹步行一個動態構造的樹,當前的計算是當前探索的節點,「其他未開發的分支」是調用堆棧/繼續?

+1

延續的要點是它們不會返回。他們是'Goto',而不是'Call'。 – Bergi

+0

沒有區別,它只是一個常規功能。 – molbdnilo

回答

1

嗯,你已經回答了你的第一個問題:技術上的區別是沒有更多的傳球延續:這是積分到這一點的緊張得到釋放的點,即積累的計算將實際執行[由一系列的β減少]。當然從語言的語義角度來看,這是一個普通的函數應用程序。

至於第二個問題,我可能會理解你錯了,但我會說每一次計算都是一個葉子樹行程,但樹不是動態構建的,而是一個靜態的(通常是無限的)對象由程序定義[唯一]。但是,接下來,調用堆棧[即使它是微不足道的,因爲尾部調用]是你已經走過的路徑(從根節點到當前節點),而繼續是你將來的路徑,從應用延續到某些事物當你應用這個事實函數時,下一個節點再次是事實,除非n是0)。

(fact _ id) 
/ \ 
(= _ 0)? otherwise 
    |   \ 
(id 1) (fact _ (λ (x) (id (* 2 x)))) 
    |  /  \ 
    1  (= _ 0)?  otherwise 
      |    \ 
     (id (* 2 1))) (fact _ (λ (x) (id (* 2 (* 1 x))))) 
      |     /  \ 
      (id 2)    (= _ 0)? otherwise 
      |     |   \ 
      2   (id (* 2 (* 1 1))) ... 
           | 
          (id (* 2 1)) 
           | 
           (id 2) 
           | 
           2 

如果你喜歡在這些方向上思考,你可能會喜歡閱讀關於這些方向的過程樹。 Hatcliff的「在線和離線部分評估簡介http://repository.readscheme.org/ftp/papers/pe98-school/hatcliff-DIKU-PE-summerschool.pdf-順便說一句PE的主題很有趣), 或許你可能會喜歡(至少在前20頁左右)斯科特的」流程圖格子「( https://www.cs.ox.ac.uk/files/3223/PRG03.pdf - 實際上,本白皮書將「更自然」翻譯爲適用的功能性語言)。

希望能給你一些見解。