Ruby には継続があります... Schemedynamic-wind
のような構造はありますか?
1 に答える
[この回答は、Schemeプログラマーを念頭に置いて書かれています(OPは以前に他のSchemeの質問をしたことがあるので、これは安全な方法です)。スキームのバックグラウンドを持たないRubyプログラマーであるためにここにいる場合は、コンテキストについて脚注を読んでください。:-)]
MRIはしません(以下を参照)。MRIがそうでない場合、それは、別の実装がそれを提供しているとしても、そのような機能を使用するための移植可能な方法がないことを意味します。
念のため、実際にMRI1.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
-rcontinuation
(MRI 1.9以降でテストするには、オプションを指定して実行するかrequire 'continuation'
、ファイルの先頭に配置する必要があります。)
aが何であるかを知らない読者にとっては、カバーされているコードが終了したときに実行されるdynamic-wind
コード(のようにensure
)と、カバーされたコードが再入力されたときに実行されるコードを指定する方法です。(これは、対象のコード内で使用し、対象のコードが終了した後に継続オブジェクトを呼び出す場合に発生する可能性があります。)call/cc
完全に考案された例:
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'