2

假設,我有下面的代碼(以類似C的語法):理解未定延續

 
void foo(int arg) { ... } 

int bar() { 
... 
// call with continuation 
... 
} 

foo (bar()) 
// after foo invocation 

1)功能調用foo功能bar,這是運行,直到它到達與call with continuation線。

2)在此行創建了一個continuation函數。它代表barfoo的其餘部分。函數continuation作爲參數傳遞給call with continuation函數。

3)call with continuation函數完成它想要的任何參數(例如它可能只是存儲在全局變量中)並返回。

4)一旦call with continuation返回,我們立即跳轉到「foo調用後」的行,其餘barfoo不執行。

5)爲了繼續barfoo執行,我們應該明確調用continuation功能,可能存儲在((2創建)(3))。一旦continuation函數被調用,執行繼續在call with continuation之後立即執行。

它是正確的嗎?我是否缺少關於無限延續的內容?

+0

您描述的行爲(第4步 - bar和foo的其餘部分未執行)只有在您可以選擇要跳過其執行的點時纔有意義。這將使*分隔*延續。然而,在像'reset' /'shift'這樣的通用定界連續API中,調用延續的行爲就像函數調用一樣,而不是跳轉,因爲在這樣的延續結束之後,它會返回到調用它的代碼。 – hzap 2011-05-28 17:50:19

回答

4

號通常情況下,未分隔延續,當你調用continuation,而不是當你調用call/cc(又名call-with-current-continuation)跳躍(例如使用計劃的call/cc創建)。

所以,充實你的例子:

continuation savedk; 

void foo(int arg) { ... } 

int bar() { 
    ... 
    call/cc(handler) 
    // after call/cc 
    println "after call/cc" 
    ... 
} 

void handler(continuation k) { 
    savedk = k 
} 

foo (bar()) 
// after foo invocation 
  1. 開始執行。我們輸入bar(我們還沒有輸入foo;當我們完成bar時,我們會這樣做)。

  2. 當我們在bar中撥打電話call/cc時,「程序上下文」變成了一個名爲continuation的對象。此時,程序上下文由「結束執行bar,然後在結果上調用foo,然後執行調用foo之後的任何操作」組成。繼續被傳遞給作爲call/cc的一個參數給出的函數,這在我上面的例子中是handler

  3. handler做了一些延續。我們假設它將其存儲在全局變量中。然後它返回call/cc呼叫之後的位置,仍在bar之內。

  4. 假設我們在這一點上打印出一些東西。然後bar完成,我們調用foo,並完成。

  5. 如果我們現在在savedk申請延續,控制跳回bar和恢復程序上下文爲「執行完畢bar,然後調用結果foo,然後做foo調用後,無論發生什麼事」。所以我們打印另一行。事實上,如果我們不清除savedk變量或測試其他某個狀態,那麼如果「在foo調用後執行任何操作」再次調用savedk,我們可能會遇到無限循環!