問題の歴史:
Perlでは、サブルーチンが最初から柔軟に実装されており、サブルーチンの呼び出しは無制限の数のパラメータを受け入れることができ、これらは配列@_に格納されます。このアプローチは、さまざまな難易度のタスクに適しており、Perlの動的性をサポートしています。
問題点:
多くの開発者、特に初心者は、@_を扱う際に混乱することがあります。これは、パラメータの不適切なデストラクチャリング、入力データの偶発的な変更(スカラーは値渡し、複雑な構造は参照渡しされるため)、引数の数とタイプの不一致といった問題です。異なるデータタイプを戻す場合や関数のプロトタイプを実装しようとすると問題が発生します。
解決策:
引数を取得するために、サブルーチンは明示的に配列@_からそれらをデストラクトする必要があります。戻り値はreturn演算子によって行われ、その動作はコンテキスト(スカラまたはリスト)によって異なります。副作用を避けるために、パラメータはしばしばコピーまたは参照で受け取られ、サブルーチン内で変更が必要な場合に使用されます。複雑な構造のためには参照渡しを使用します。
コード例:
sub add { my ($a, $b) = @_; return $a + $b; } sub change_array { my ($arr_ref) = @_; push @$arr_ref, 100; } my @nums = (1, 2, 3); my $sum = add(5, 10); change_array(\@nums); print join(", ", @nums); # 1, 2, 3, 100
主な特徴:
@_を通じて渡す関数が受け取ったパラメータは、単純なスカラーと作業する場合に変更されるのか?
いいえ、スカラーは値渡しのため、変更は元のものに影響しません。しかし、引数が参照であれば、元のデータが変更される可能性があります。
他の言語と同様に、サブルーチンにデフォルト引数値を指定できますか?
直接的にはできません。Perlでは、デフォルト値の処理を関数本体内で、自身で実装する必要があります。definedのチェックや引数の数を使用します。
コード例:
sub foo { my ($arg1, $arg2) = @_; $arg2 //= 10; print "$arg1 $arg2 "; } foo(5); # 5 10
@をコピーせずに直接アクセスした場合、例えば $a = $[0]?
そのような代入はエイリアスを作成します: $aの変更は$_[0]をも変更し、その逆もまた然りです。期待しない変更を避けるためには、my ($a) = @_を使ってコピーを作成することをお勧めします。
** ネガティブケース
配列を処理する関数内で、@_からローカル変数にパラメータをコピーするのを忘れました。その結果、ローカル変数の変更が元の配列に影響を与え、プログラムの他の部分にバグを引き起こしました。
利点:
欠点:
** ポジティブケース
チームは、各サブルーチンの最初に@_の必須デストラクチャリングを導入し、大きなオブジェクトは参照でのみ渡すことにしました。
利点:
欠点: