2011-04-12 37 views
4

我想讀這個代碼:這個Scheme列表迭代器如何使用call-with-current-continuation?

(define list-iter 
    (lambda (a-list) 
    (define iter 
     (lambda() 
     (call-with-current-continuation control-state))) 
    (define control-state 
     (lambda (return) 
     (for-each 
      (lambda (element) 
      (set! return (call-with-current-continuation 
          (lambda (resume-here) 
          (set! control-state resume-here) 
          (return element))))) 
      a-list) 
     (return 'list-ended))) 
    iter)) 

任何人都可以解釋這個例子如何call-with-current-continuation作品?

由於

+0

關於SO可能還有其他的「什麼是call/cc」問題的重複。我能找到的最具規範和顯然有用的人:http://stackoverflow.com/questions/612761/what-is-call-cc。 – amalloy 2011-04-12 03:19:03

+1

我想到了這個具體的例子,使用類似「yield」的模式,足以證明自己的價值。不過,也許它應該被重新命名。 – acfoltzer 2011-04-12 03:23:09

回答

3

call-with-concurrent-continuation,或call/cc短的實質,是一個程序的執行過程中抓住的檢查點,或延續,的能力。然後,您可以通過將它們應用爲功能來回到這些檢查點。

這裏有一個簡單的例子,在不使用的延續:

> (call/cc (lambda (k) (+ 2 3))) 
5 

如果你不使用的延續,這是很難分辨出來。下面是一些我們真正使用它:

> (call/cc (lambda (k) (+ 2 (k 3)))) 
3 
> (+ 4 (call/cc (lambda (k) (+ 2 3)))) 
9 
> (+ 4 (call/cc (lambda (k) (+ 2 (k 3))))) 
7 

當調用延續,控制流跳回到那裏繼續被call/cc抓住。將call/cc表達式看作是一個洞,它會被傳遞給k的任何東西填充。

list-iter是一個相當複雜的使用call/cc,並且可能是一個開始使用它的困難地方。首先,這裏有一個例子用法:

> (define i (list-iter '(a b c))) 
> (i) 
a 
> (i) 
b 
> (i) 
c 
> (i) 
list-ended 
> (i) 
list-ended 

這裏是發生了什麼事的草圖:

  1. list-iter返回的沒有參數i的過程。
  2. i被調用時,我們立即獲取延續並將其傳遞給control-state。當這個延續,調用return,我們會立即返回誰調用i
  3. 對於列表中的每個元素,我們抓取一個新的延續並用新的延續覆蓋control-state的定義,這意味着我們將在下一次第2步時繼續。
  4. 在下一次設置control-state之後,我們將列表的當前元素傳遞迴return延續,產生列表的一個元素。
  5. 當再次調用i時,請重複步驟2,直到for-each已完成整個列表的工作。
  6. 'list-ended調用return繼續。由於control-state未更新,因此每次調用i時都會返回'list-ended

正如我所說,這是一個相當複雜的使用call/cc,但我希望這是足以通過這個例子。爲了更加溫和地介紹延續,我建議你拿起The Seasoned Schemer

0

基本上它的功能是f作爲其參數,並將f應用於程序的當前上下文/狀態。

維基百科:
(define (f return)
(return 2)
3)

(display (f (lambda (x) x))) ; displays 3

(display (call-with-current-continuation f)) ; displays 2

所以基本上當f被稱爲無電流延續(CC),該函數被施加到2 ,然後返回3.使用current-continuation時,應用該參數到2,強制程序跳轉到當前繼續被調用的位置,並返回2.它可用於生成回報或暫停執行流程。

如果您瞭解C,請考慮這樣:在C中,您可以使用指向函數的指針。你也有回報機制。假設返回帶有一個與函數所用類型相同的參數。假設你可以獲取地址並將該地址存儲在一個變量中,或者將其作爲參數傳遞,並允許函數返回給你。它可以用來模仿throw/catch,或者作爲協程的機制。

0

這基本上是:

(define (consume) 
    (write (call/cc control))) 

(define (control ret) 
    (set! ret (call/cc (lambda (resume) 
         (set! control resume) 
         (ret 1)))) 
    (set! ret (call/cc (lambda (resume) 
         (set! control resume) 
         (ret 2)))) 
    (set! ret (call/cc (lambda (resume) 
         (set! control resume) 
         (ret 3))))) 

(consume) 
(consume) 
(consume) 

希望這是更容易理解。