Programmingフルスタック Perl デベロッパー

Perlのサブルーチンに引数を渡す方法は何がありますか?参照渡しをどのように実現しますか?@_の動作の細かい点は何ですか?参照渡しが必要な場合とはどのような場合ですか?

Hintsage AIアシスタントで面接を突破

答え

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)

細かい点:

  • 元の配列やハッシュを変更したい場合は、_参照_を渡してください。
  • @_内の通常の変数($foo, $bar)は、元の引数のエイリアスですが、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)

歴史

APIフレームワークを作成する際、関数に多数の名前付き引数をハッシュを使用して渡していました。時には、配列を渡すことがありました(ただし、参照ではありません!)。この場合、引数が「混在」し、混乱を引き起こしました:myfunc(@arr, %opts)。ハッシュの一部のキーが配列の値で上書きされることが分かり、エラーを発見するのが難しくなりました。

歴史

木構造の再帰的な走査を実装する際、内部要素を変更したいという要望がありました。配列を「そのまま」渡しましたが、参照ではありませんでした。これによりコピーが作成され、変更が外部コンテキストに影響を与えませんでした。この問題は渡し方を参照スタイルに置き換えることで解決されました。