Perlでは、関数の引数はすべて@という配列を介して行われます。サブルーチンを呼び出すと、渡されたすべてのパラメータがこの配列に入ります。初めはリストであり、コピーではありません。つまり、$[0]を変更すると元の値が変更されます。
sub foo { my ($arg1, $arg2) = @_; $arg1 = 10; # ローカル変数のみが変更される }
sub bar { my ($array_ref) = @_; push @$array_ref, 42; } my @data = (1,2,3); bar(\@data); # @dataは今や (1,2,3,42)
my ($a, $b) = @_で展開するとコピーが作成されます。Perlで関数に配列をこのように渡した場合:
myfunc(@arr)、関数内で$_[0]にアクセスすると、そこには何がありますか?
正しい答え: そこにあるのは配列の_最初の値_であり、配列全体への参照ではありません!配列をまとめてオブジェクトとして渡したい場合は、参照を使用してください:myfunc(\@arr)。
sub print_first { print $_[0], " "; } my @a = qw/foo bar baz/; print_first(@a); # 'foo'が出力されるが、配列への参照ではない print_first(\@a); # ARRAY(0x...) — 配列全体への参照が出力される
歴史
update_hash(%global)のようにしていました。内部で$_[0]を変更していました。その結果、変更されたのは引数のローカルスライスだけで、グローバルハッシュ自体は修正されませんでした。正しい解決策は参照を渡すことでした:update_hash(\%global)。歴史
myfunc(@arr, %opts)。ハッシュの一部のキーが配列の値で上書きされることが分かり、エラーを発見するのが難しくなりました。歴史
木構造の再帰的な走査を実装する際、内部要素を変更したいという要望がありました。配列を「そのまま」渡しましたが、参照ではありませんでした。これによりコピーが作成され、変更が外部コンテキストに影響を与えませんでした。この問題は渡し方を参照スタイルに置き換えることで解決されました。