Array#eachっぽいのを実装
プロトタイプ宣言の練習にRubyのeachを書いてみた。
sub myeach(&@) { my ($block, @array) = @_; for my $item (@array) { &$block($item); } return [@array] }
実行結果は以下の通り、
pirl @> myeach { my $item = shift; printf("%d\n", $item * $item) } (1..10); 1 4 9 16 25 36 49 64 81 100 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
$_がそのまま使えないのはなぜだろう。というよりは、ブロックを受け取るプロトタイプ宣言で
受け取るブロックの引数を決め打ちできないかなぁ…。
こうすれば良いのに気づいた…。
sub myeach(&@) { my ($block, @array) = @_; for my $item (@array) { &$block($_ = $item); } return [@array] }
これでこんな感じでも実行できるようになる。
pirl @> myeach { printf("%d\n", $_ * $_) } (0..10); 0 1 4 9 16 25 36 49 64 81 100 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
追記
fbisさんのコメントによりforeachや組み込みメソッドなどの自動的に$_を置き換えるような関数内でこのようなことをするとエラーになることを教えていただきました。
&$block(local $_ = $item);
とすれば、ブロックのスコープから抜けた後で$_が元の値に戻るため大丈夫なようです。