遠藤です。 > 親子関係を利用したプログラミングをしている場合、「親子関係の > 破壊を起こさなければ」、Fiber#prev が正しく「呼び出し元」を指 > し示すため、SemiCoroutine のような使い方が可能です。 今の Fiber で「親子関係を壊さない範囲」というのはものすごく 狭いと思います。coroutine の中で coroutine を呼び出して suspend を受けるだけで違反してしまいます。 ささださんの Generator の例も、generator の中で generator を呼ぶと違反している気がします (ちゃんと追ってないので勘違いだったらすみません) 。 show Generator.new{|g| g.yield 10 show Generator.new{|g2| g2.yield 100 g2.yield 200 g2.yield 300 } g.yield 20 g.yield 30 } $ ./test.rb 100 200 300 ./test.rb:31:in `initialize': unhandled exception from ./test.rb:79:in `new' from ./test.rb:79:in `<main>' 親を自力で管理して、Fiber.new のブロックの最初で @parent = Fiber.prev || Fiber.root で親を保存して、@fib.suspend の代わりに @parent.yield をすれば動いたような気がしますが、まだ間違ってる気がします。 Fiber.new のブロックの最後でも @parent.yield しないとダメな気も しますが、今のところ動かない例は見つけられていません。あと、 g = Generator.new{|g| g.yield 10 g.yield 20 g.yield 30 } Fiber.new do show g end.yield が何も出力されないというよくわからない挙動をしますが、 これも Fiber をよくわかってないことが原因の「不思議なこと」でしょうか。 > 余談ですが、現在の Ruby の Continuation は欠陥品で、まともに > 利用できないシロモノです。具体的には、dynamic-wind 相当の機能 > がありません。なので、「xx の代わりに Continuation を利用」と > いう選択肢はありえないと考えています。 これは、対等な関係は必要なのかなぁ、といういい加減な気持ちから 適当言いました。すみません。 ちなみに Lua の開発陣?の例の論文によると、semi-coroutine で coroutine をエンコードできると主張されてました。 # 補助 coroutine を立ち上げて、TRANSFER するときは全てその # 補助 coroutine を介して呼ぶ感じです。トランポリン? dynamic-wind についてはお察しの通りよくわかってませんが、例えば 「ブロックを取るメソッドを書くとき、そのメソッドを使う人が callcc でブロックの中に飛び込むようなことをしたときの対策が とれない」ってことでしょうか。 callcc は (楽しい楽しい) 黒魔術なので、そういうときは callcc 使用者側の責任だと思っています。あいまいなスタンスですが、外部 ライブラリなしの状態で SEGV しなければ十分かなー、みたいな。 # 私に関しては、普段のプログラミングでは callcc 使いません。 # ぶっちゃけ「おもちゃ取るな!」というレベルの主張です。すみません。 > 個人的には、「主観的な感想」ではたぶん説得力がない気がするの > で、実際にいくつか現実的な例を出して、プログラミングをしてみて > から考えるのがいいような気がしています。 ごもっともですが、下手に他の言語で十分練られた設計があるなら それを盗むのも手かと思わなくもないです。 -- Yusuke ENDOH <mame / tsg.ne.jp>