From: "5.5" <5.5@...> Date: 2011-04-15T21:54:43+09:00 Subject: [ruby-list:47977] Re: Fiber#resumeの引数について 5.5 です。 (11/04/15 17:55), Satoshi GUNJI wrote: > 郡司と申します。 > > [ruby-list:47973]を見ていてちょっと気になったので、 > Fiberの挙動を確かめるために下記のサンプルコードを実行してみました。 > > -------- > f = Fiber.new do > Fiber.yield 1 > Fiber.yield 2 > Fiber.yield 3 > end > > puts f.resume > puts f.resume > puts f.resume > puts f.resume(8) > -------- > > すると、次のような実行結果となりました。 > > -------- > 1 > 2 > 3 > 8 > -------- とくにおかしくはないと思います。 話を簡単にするために規模を縮小します。行番号も付け, 説明の都合上,やりとりする値をシンボルにします。 1: f = Fiber.new do 2: Fiber.yield(:foo) 3: end 4: 5: puts f.resume 6: puts f.resume(:bar) 5 を評価するとき,まず,f.resume を評価します。すると f のブロックの中を評価しようとします。 最初に Fiber.yield(:foo) があるので,これを評価しよう とします。 すると,親ファイバーに戻ってきますが,そのときに :foo が渡されます。 5 は結局,puts :foo を評価することになります。 ところで,この時点では 2 の評価は終わっていません。 次に 6 を評価しようとします。 まず,f.resume(:bar) を評価しようとします。 すると,また子ファイバーのほうに行きますが,このとき :bar が子ファイバーのほうへ渡されます。 そして,ようやく 2 の評価が終わります。 Fiber.yield の返り値は,親ファイバーから渡された :bar です。 ※このことはリファレンスマニュアルの Fiber.yield のと ころに書いてあります。 そして,ブロックの評価は完了しました。 ブロックの評価値は,2 の評価値である :bar です。 ブロックの評価が終わったので,また親ファイバーに戻って きますが,そのときにブロックの評価値が渡されて,それが 6 の f.resume(:bar) の値となります。 したがって,:bar がプリントされます。 なお,2 を puts Fiber.yield(:foo) と書き換えればより理解しやすいと思います。 先に書きましたが,Fiber.yield や Fiber#resume の値を捨 てるようなサンプルスクリプトを使うと理解しづらいです。 私はそれでだいぶ悩みました。 -- 5.5@moji.gr.jp