Hatena::ブログ(Diary)

このブログは証明できない。

2008-10-24

[]Rubyの継続でフィボナッチ(継続の初歩)

Rubyには継続(continuation)という仕組みが用意されています。Scheme以外で継続が使われるケースは少ないと聞いたような気がしますが、せっかく用意されているので今さらながら使ってみます。


いい例が思いつかなかったのですが。こんなカンジで。

value = callcc {|$c| 0 }        #...(1)
value = $c.call 1 if value == 0 #...(2)
puts value #=> 1

(1)のところの「世界」をグローバル変数$cに保存しつつ、0を返しています。そして、(2)のところで、(1)で保存した「世界」にジャンプします。(2)から(1)に戻るイメージなのですが、「戻る」という言葉はふさわしくありません。(1)の「世界」の続きを実行する。

callcc() は、ブロックの戻り値を返しますが、Continuation#call(args) が呼び出されたときは args を返します。

プログラミング言語 Ruby リファレンスマニュアル

(1)ではブロックの戻り値0を返しています。(2)では、引数1が返ります。


ちょっと改造。

value = callcc {|$c| 0 }
value = $c.call value + 1 if value < 5
puts value #=> 5

ジャンプする回数を増やしました。


例が悪いですね。。。


本題。継続を使ってフィボナッチ数列を出力します。

def fib
  a, b = callcc {|$c| [0,1] }
  puts b
  $c.call b, a + b  if b < 100
end

fib

上の例が解れば、やってることは同じなので難しくはないと思います。


callccはcall with current continuationを意味します。私はC言語には詳しくないのですが、C言語のsetjmp/longjmpと同じようなカンジだそうです。それで、継続を使うと何がウレシイのか?よく出てくるのは大域脱出ですね。ネストしたループから一気に外側まで脱出できます。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証