Bug #1018(return in an eigenclass definition) の難しさについて
絶対忘れるのでメモ。というかさっきまで忘れてました。たとえばこんなケース。
def foo
bar {|o| return o }
end
この return が実行されるとき、FINISHとかTOPとかを除くと、フレームは
ブロックのフレーム の上に barのフレーム の上に fooのフレーム
となっているわけです。で、この return は bar からの return ではなく foo からの return として処理しなければなりません。とすると、フレームをたどるときに return の対象ではない bar は無視しなければなりません。
この判定に、現在の trunk ではスコープを用います。つまり、return が実行されたフレームと同一スコープのメソッドフレームを検索し、これに対して return 処理をします。うまくできてますね。
うまくできているのですが、この実装のために、題のチケットに行き着くわけです。クラス宣言が始まった時点でスコープが変わってしまうので、ここで return すると対象のメソッドフレームが見つからなくなってしまいます。そこで現在はコンパイル時点でこれは禁止されています。
んじゃあスコープ以外で判定するか、というとこれも中々で。別の場所で作られたProcオブジェクトをブロックとして渡されて、しかもその中に return が入ってたらどうするか、なんて面倒な問題にもなるわけで、結局スコープで処理するのが一番確実かつ楽だと思うわけです。さてどうしよう。
def bar
yield
end
def foo(&b)
bar {class <<self;return ;end} if b == nil
bar(&b)
return 2
end
p foo
p foo{return :ng}
こんなんなるともう、何がなにやら。
トラックバック URI : http://www1.atword.jp/wannabe/2009/08/02/bug-1018return-in-an-eigenclass-definition-%e3%81%ae%e9%9b%a3%e3%81%97%e3%81%95%e3%81%ab%e3%81%a4%e3%81%84%e3%81%a6/trackback/
コメント (0)