2011-11-10 28 views
3

我有點了解如何將基本功能(如運算法則)轉換爲Scheme中的延續傳球風格。 但是,如果函數涉及遞歸呢? 例如,計劃 - 轉換爲延續傳球風格

(define funname 
    (lambda (arg0 arg1) 
       (and (some procedure) 
         (funname (- arg0 1) arg1)))) 

請給我意見。 預先感謝您。

回答

1
(define (func x y k) 
    (some-procedure 
    (lambda (ret) 
    (if ret 
     (- x 1 
      (lambda (ret) 
       (func ret y k))) 
     (k #f)))) 

你所缺乏的基本情況,這就是爲什麼要延續的唯一顯式調用是(k #f)。如果你有一個基本情況,那麼你也可以將基本情況返回值傳遞給繼續。例如:

有上延續了很好的解釋和CPS是Krishnamurthi的 PLAI
(define (func x y k) 
    (zero? x 
     (lambda (ret) 
      (if ret 
       (k y) 
       (some-procedure 
       (lambda (ret) 
        (if ret 
         (- x 1 
         (lambda (ret) 
          (func ret y k))) 
         (k #f)))))))) 
4

一個地方。相關部分(VII)不依賴於書籍的其他部分,因此您可以在此處跳到其他部分。特別是一個將代碼手動轉換爲CPS並解決遞歸函數的擴展示例(第17章的第一部分)。

此外,我爲我的班級寫了一篇extended version的文章,其中有更多的例子和關於這個主題的更多細節 - 你也許會覺得這很有用。除PLAI文本之外,我還介紹了一些常見的延續實現,比如實現生成器,模糊運算符等等。 (但請注意,PLAI繼續討論實施策略,這是我的文本未涉及的部分。)

1

這部分重複Chris Jester-Young的回答,但是,我希望我能更好地解釋它:-)。

在CPS,你正在尋找不同的是這兩件事情(大約)之間:

  • 您可以調用過程,並通過它你通過了延續。這相當於直接式優化的尾部呼叫。
  • 或者,您可以調用一個過程,並將其繼續傳入一個新的過程,該過程使用「返回值」執行某些操作,從而傳遞原始的繼續。這相當於直接式堆棧調用。

後者就是克里斯例子中的lambda表達式。基本上,評估一個lambda創建一個閉包 - 這些閉包用於執行堆棧框架在執行直接樣式程序時所做的相同工作。代替棧幀中的返回地址,閉包包含一個連續函數的綁定,閉包的代碼調用它。