2011年4月15日

[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@xxxxx


投稿者 xml-rpc : 2011年4月15日 21:54
役に立ちました?:
過去のフィードバック 平均:(0) 総合:(0) 投票回数:(0)
本記事へのTrackback: http://hoop.euqset.org/blog/mt-tb2006.cgi/103114
トラックバック
コメント
コメントする




画像の中に見える文字を入力してください。