現在、『On Lisp』が3巡目の終盤に差し掛かっている。でも、いまいち継続を理解できていない。分かり易い解説を見つけたのでPerlに翻訳してみた。(本を読む FizzBuzzとGaucheで学ぶ継続の基礎)
use strict; use warnings; sub fizzbuzz { my ($next, ($n)) = @_; my $answer = $n % 15 == 0 ? "FizzBuzz" : $n % 3 == 0 ? "Fizz" : $n % 5 == 0 ? "Buzz" : $n; # $nextを挟んで再帰呼び出し $next->(\&fizzbuzz, ($n + 1, $answer)); } sub continuation { my ($next, ($n, $answer)) = @_; # 状態を閉じ込めた状態で関数終了 my $cc = sub { my ($fun) = @_; $fun->($answer) if (ref $fun eq 'CODE'); $next->(\&continuation, ($n)); }; } # 1〜100のfizzbuzz継続を生成してリストに保存 my @restart = fizzbuzz(\&continuation, (1)); push @restart, $restart[$#restart]->() for 2..100; # 1〜100のfizzbuzz継続を実行 $restart[$_]->( sub{ print @_, $_ != $#restart ? '|' : '' } ) for 0..$#restart;
100までのFizzBuzzが表示される。
1|2|Fizz|4|Buzz|Fizz|7|8|Fizz|Buzz|11|Fizz|13|14|FizzBuzz|16|17|Fizz|19|Buzz|Fiz z|22|23|Fizz|Buzz|26|Fizz|28|29|FizzBuzz|31|32|Fizz|34|Buzz|Fizz|37|38|Fizz|Buzz |41|Fizz|43|44|FizzBuzz|46|47|Fizz|49|Buzz|Fizz|52|53|Fizz|Buzz|56|Fizz|58|59|Fi zzBuzz|61|62|Fizz|64|Buzz|Fizz|67|68|Fizz|Buzz|71|Fizz|73|74|FizzBuzz|76|77|Fizz |79|Buzz|Fizz|82|83|Fizz|Buzz|86|Fizz|88|89|FizzBuzz|91|92|Fizz|94|Buzz|Fizz|97| 98|Fizz|Buzz
- fizzbuzz関数からcontinuation関数が呼ばれる。continuation関数はfizzbuzz関数を呼び出す関数を返す。
- ↑が返した関数を呼び出すとfizzbuzz関数が呼ばれる。fizzbuzz関数からcontinuation関数が呼ばれ、fizzbuzz関数を呼び出す関数を返す。
- 以下、同じことの繰り返し。
# 90のfizzbuzz print "90 = "; $restart[90-1]->( sub { print @_, "\n" } ); # 4のfizzbuzz print "4 = "; $restart[4 -1]->( sub { print @_, "\n" } ); # 70のfizzbuzz print "70 = "; $restart[70-1]->( sub { print @_, "\n" } );
保存してある継続を使って指定した数値のFizzBuzzを表示することもできる。
90 = FizzBuzz 4 = 4 70 = Buzz
分かったような分からないような・・・
修行が足りない。