読者です 読者をやめる 読者になる 読者になる

Array#eachっぽいのを実装

perl

プロトタイプ宣言の練習に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);

とすれば、ブロックのスコープから抜けた後で$_が元の値に戻るため大丈夫なようです。