web-dev-qa-db-ja.com

Perlの関数に配列を渡す

Perlの関数に渡される引数のいくつかの側面を誤解したと思います。 func(\@array)func(@array)の違いは何ですか?

AFAIK、両方の関数で、引数は参照によって渡され、両方の関数で、メインプログラムの@arrayの要素を変更できます。では、違いは何ですか?いつどちらを使うべきですか?

@array = (1,2,3);
func(@array);
func(\@array);

sub func {
    ...
}

また、Perlで値渡しを模倣するにはどうすればよいですか? @_を使用する唯一の方法ですか?

15
aminfar

AFAIK、両方の関数で、引数は参照によって渡され、両方の関数で、メインプログラムの@arrayの要素を変更できます。

「の要素を変更する」、はい。ただし、func(@array)の場合、subには、配列に他の変更を加える手段がありません(配列の切り捨て、プッシュ、ポップ、スライス、他の何かへの参照の受け渡し、さらには定義解除)。

メカニズムはPerlの参照とは完全に異なるため、「参照によって渡される」という用語の使用は避けます。過負荷が少ない:)サブで@_の要素は、サブに渡された要素にエイリアスされて開始されます。

13
ysth

配列を潜水艦に渡すことは不可能です。潜水艦は引数としてスカラーのリストを取ります。 (そして、それは彼らが返すことができる唯一のものです。)

配列への参照を渡すことができます。

func(\@array)

配列の要素を渡すことができます。

func(@array)

いつどちらを使うべきですか?

配列の要素以外のものを渡したい場合(例:pass $x$yおよび@a)、参照を渡さない限り、注意が必要になる場合があります。

リストを処理する場合(例:sum mysub grep { ... } ...)、参照を渡したくない場合があります。

(配列の既存の要素を変更するだけでなく)配列を変更する場合は、参照を渡す必要があります。

大きな配列の各要素のエイリアスを作成するよりも、1つの参照を作成してスタックに配置する方が高速であるため、長い配列の参照を渡す方が効率的です。ただし、これが問題になることはめったにありません。

通常、上記の最初の2つのうちの1つによって決定されます。それを超えて、それは主に個人的な好みの問題です。


また、Perlで値渡しを模倣するにはどうすればよいですか?
sub foo {
   my ($x) = @_;   # Changing $x doesn't change the argument.
   ...
}

sub foo {
   my @a = @_;   # Changing @a or its contents
   ...           #    doesn't change the arguments.
}
20
ikegami

func(\@array)は参照を渡します。 func(@array)は(@arrayの要素の)リストを渡します。キースが指摘したように、これらの要素は参照によって渡されます。ただし、値を渡すために、サブ内にコピーを作成できます。

あなたが求めているのはこれです:

sub func {
    my @array = @_;
}

これにより、funcの引数のコピーが@arrayに渡されます。これは、サブルーチンのスコープ内のローカル変数です。

ドキュメント ここ

4
TLP