2010-10-06 23 views

回答

5

[這個答案是寫在Scheme程序員的腦海裏(OP已經詢問過其他Scheme的問題,所以這是一個安全的選擇)。如果您因爲您是沒有Scheme背景的Ruby程序員而來到這裏,請閱讀腳註以瞭解某些上下文。 :-)]

MRI沒有(見下文);如果MRI沒有,那就意味着即使另一個實現提供了這種功能,也沒有可移植的方法來使用這些功能。

我確實檢查了MRI 1.9.1源代碼。無論如何,下面是一些代碼,用於證明即使是正常的放鬆保護(ensure)也不能在MRI上進行延續(使用1.8.7和1.9.1進行測試)。 (它使用JRuby正常工作(我用1.5測試),所以它正好說明它的具體實現的事情。但需要注意的是JRuby的只提供逃跑的延續,而不是通用的。)

callcc do |cc| 
    begin 
    puts 'Body' 
    cc.call 
    ensure 
    puts 'Ensure' 
    end 
end 

(與MRI 1.9+測試,你需要或者與-rcontinuation選項運行,或將require 'continuation'在文件的頂部。)


對於讀者誰不知道dynamic-wind是什麼,這是一個辦法在退出代碼時指定要運行的代碼(很像ensure),以及代碼在重新輸入代碼時運行。 (這可能發生在使用call/cc涵蓋代碼中,並調用continuation對象的覆蓋的代碼已經退出後)。

完全人爲的例子:

def dynamic_wind pre, post, &block 
    raise 'Replace this with a real implementation, kthx' 
end 

def redirect_stdout port, &block 
    saved = $stdout 
    set_port = lambda {$stdout = port} 
    reset_port = lambda {$stdout = saved} 
    dynamic_wind set_port, reset_port, &block 
end 

cc = nil 
# cheap way to nuke all the output ;-) 
File.open '/dev/null' do |null| 
    redirect_stdout null do 
    callcc {|cc|} 
    puts 'This should not be shown' 
    end 
    puts 'This should be shown' 
    cc.call 
end 

所以,正確運作dynamic_wind實施將確保在調用延續時$stdout將被設置回/dev/null流,以便在運行puts 'This should not be shown'的所有實例中確實不顯示該文本。