mapとgrepは、配列を操作するためのPerlの強力な関数です:
my @nums = (1, 2, 3, 4, 5, 6); my @squared = map { $_ * $_ } @nums; # (1, 4, 9, 16, 25, 36) my @even = grep { $_ % 2 == 0 } @nums; # (2, 4, 6)
mapとgrepのブロック内で、変数$_はデフォルトで現在の要素を含みます。$_を修正すると、配列が参照渡しされている場合やforeachで別名が使用されている場合に、元の配列の要素自体が変更されることがあります。mapは常にリストを返し、grepは元のリストのサブセットを返します。質問: 次のコードは何をし、なぜですか?
my @nums = (1..5); my @result = map { $_++ } @nums; print "@nums ";
回答: このコードは元の配列@numsを変更しません。演算子$_++はブロック内の変数の値を増やしますが、元の配列にはその変更は保存されません。なぜなら、mapは変更された値を返しますが、元の配列は影響を受けないからです(foreachで別名が使用されている場合を除く)。
my @nums = (1..5); my @result = map { $_++ } @nums; # @resultは(1,2,3,4,5)となり、@numsは変わりません print "@nums "; # 出力: 1 2 3 4 5
ストーリー あるプロジェクトで、開発者は
map { $_++ } @arrayの後に、配列@arrayが変更されると期待していました。その結果、プログラムは古い値のまま動作し、データの集計時に不正確な計算を引き起こしました。
ストーリー レポートシステムでは、配列を
grepでフィルタリングする際、ブロック内で間違って$result = $_という代入文を使用してしまい、すべての要素が同じ変数に上書きされ、データソースが失われました。これによりデバッグが難しくなり、レポートに損失をもたらしました。
ストーリー 統合スクリプト内で、ネストされた
mapを使用し、内部コンテキストも共通の変数$_で動作することを忘れたため、要素の変更時に予測不可能な動作が発生しました。内部のmapが結果の配列に値を上書きしました。