2

Ruby には継続があります... Schemedynamic-windのような構造はありますか?

4

1 に答える 1

5

[この回答は、Schemeプログラマーを念頭に置いて書かれています(OPは以前に他のSchemeの質問をしたことがあるので、これは安全な方法です)。スキームのバックグラウンドを持たないRubyプログラマーであるためにここにいる場合は、コンテキストについて脚注を読んでください。:-)]

MRIはしません(以下を参照)。MRIがそうでない場合、それは、別の実装がそれを提供しているとしても、そのような機能を使用するための移植可能な方法がないことを意味します。

念のため、実際にMRI1.9.1のソースコードを調べました。いずれにせよ、ここに、通常の巻き戻し保護()でさえensureMRIの継続で正しく機能しないことを示すいくつかのコードがあります(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/nullputs 'This should not be shown'

于 2010-10-07T04:22:32.333 に答える