Lmap/filter の引数に $_ を
Lmap/filterの第一引数には sub を省略した無名サブルーチンを使えますが,そのサブルーチンの引数は一個で,$_[0] を使います.一方,Perlの組み込みのmap/grepでは,デフォルトの $_ を使います.そこで,Lmap/filterでも同じように $_ に変更してみます.
sub Lmap(&$){ my ($f, $l) = @_; my $trans =sub{ local $_=shift; $f->(); }; return unless $l; node ($trans->(head($l)), &Lmap($f, tail($l)) ); } sub filter(&$){ my ($f,$l) = @_; my $checker = sub{ local $_ = shift; $f->(); }; return unless $l; my $temp=head($l); if ($checker->($temp)){ node($temp, &filter($f,tail($l))); }else{ &filter($f,tail($l)); } }
localで $_ の値をサブルーチンの中でだけ引数にして,それをLmap/filterの第一引数の中の $_ として使うというトリックです.$_ はグローバル変数ですが,この処理で局所化できます.
ここでわかるのは「無名サブルーチンの中は評価されない」というか「実際に呼び出されたときに評価される」という遅延評価っぽいことが起こることです.Lmap/filterの引数として使われた段階で $_ が評価されてしまったら当然困ってしまいますので,そういうことはないということです.
この変更で
my $a=[ 1, [2, [ 3, [4,undef ] ] ] ]; print Dumper (Lmap {$_ * 2} $a); print Dumper (filter {$_ % 2} $a); $VAR1 = [ 2, [ 4, [ 6, [ 8, undef ] ] ] ]; $VAR1 = [ 1, [ 3, undef ] ];
と出てくるようになりました.