dankogai 2012/08/26 01:48
http://blog.livedoor.jp/dankogai/archives/51059559.html
ありがたい先人の知恵に従ってみるとだいぶシンプルになって素晴らしいのだけど、dump_listの戻り値のvoidを評価させるのが泥臭くなった。
use strict; use warnings; use Scalar::Lazy qw(lazy); sub nil() { lazy { 'NIL' } } sub concat($$) { my ($x, $xs) = @_; lazy { [$x, $xs] }; } sub dump_list($) { my $xs = shift; if ($xs->[1] eq nil) { print $xs->[0], "\n"; return lazy { }; } else { print $xs->[0], ", "; return lazy { dump_list ($xs->[1]) }; } } sub repeat($); sub repeat($) { my $x = shift; lazy { concat($x, lazy { repeat $x }) }; } sub head($) { my $xs = shift; $xs->[0]; } sub take($$); sub take($$) { my ($xs, $n) = @_; return lazy { nil } if $n == 0; lazy { concat $xs->[0], lazy { take $xs->[1], lazy { $n - 1 } } }; } print head(lazy { concat lazy { 1 }, lazy { concat lazy { 2 }, lazy { nil } } }), "\n"; print head lazy { repeat lazy { 1 } }, "\n"; dump_list lazy { take lazy { repeat lazy { 1 } }, lazy { 3 } } or undef;