在表達式(call/cc (lambda (k) (k 12)))
,有三個延續:(k 12)
,(lambda (k) (k 12))
,和(call/cc (lambda (k) (k 12)))
。哪一個是「當前延續」?下列表達式的當前延續是什麼?
而且在一些書的延續被視爲其正在等待值的過程,當它應用到值,它將立即返回。是對的嗎?
任何人都可以解釋什麼目前的延續是詳細的?
在表達式(call/cc (lambda (k) (k 12)))
,有三個延續:(k 12)
,(lambda (k) (k 12))
,和(call/cc (lambda (k) (k 12)))
。哪一個是「當前延續」?下列表達式的當前延續是什麼?
而且在一些書的延續被視爲其正在等待值的過程,當它應用到值,它將立即返回。是對的嗎?
任何人都可以解釋什麼目前的延續是詳細的?
之類的東西(k 12)
不延續。在更大的程序中,每個子表達式都有一個延續。例如,(* 3 (+ x 42))
中的x
的延續是(lambda (_) (* 3 (+ _ 42)))
。
在您的例子中,(call/cc (lambda (k) (k 12)))
「當前延續」將是無論是周圍的表達。如果您只是將它輸入到方案提示中,則沒有任何方法提示,因此「當前延續」僅爲(lambda (_) _)
。如果您鍵入的內容類似(* 3 (+ (call/cc (lambda (k) (k 12))) 42))
,則繼續爲(lambda (_) (* 3 (+ _ 42)))
。
請注意,用於表示「當前延續」的lambda表達式與call/cc
傳入的不同(在您的示例中,名稱爲k
)。 k
在評估當前延續後具有中止計算的其餘部分的特殊控制效果。
在這種情況下,延續是接收call/cc
調用的返回值的「東西」。因此:
(display (call/cc (lambda (k) (k 12)))
具有相同的結果
(display 12)
延續方案「外觀和感覺」之類的程序,但它們實際上並不表現得像程序。有一件事可以幫助你更好地理解延續是CPS轉型。
在CPS轉換中,不是返回值的函數,而是接受一個繼續參數,並用結果調用延續。所以,一個CPS轉換的函數將被(sqrt 64 k)
調用,而不是返回8,它只調用尾部位置的(k 8)
。
由於延續(在CPS變換函數)是尾部調用,該函數不擔心繼續回來,事實上,在大多數情況下,他們預計不會返回。
考慮到這一點,這裏有一個功能的一個簡單的例子:
(define (hypot x y)
(sqrt (+ (* x x) (* y y))))
和CPS-轉換後的版本:
(define (hypot x y k)
(* x x (lambda (x2)
(* y y (lambda (y2)
(+ x2 y2 (lambda (sum)
(sqrt sum k))))))))
(假設*
,+
,並且sqrt
已全部CPS也轉化爲接受延續論證)。
所以現在,有趣的部分:一個CPS轉化call/cc
具有以下定義:
(define (call/cc fn k)
(fn k k))
隨着CPS轉換,call/cc
是容易理解和容易實現。沒有CPS轉換,call/cc
可能需要高度神奇的實現(例如,通過堆棧複製等)。