2010-10-06 29 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'的所有实例中确实不显示该文本。