13

2 つの配列を持つと予想されるサブルーチン内で引数の受け渡しと読み取りに問題があります。

sub two_array_sum { # two_array_sum ( (1 2 3 4), (2, 4, 0, 1) ) -> (3, 6, 3, 5)
  # I would like to use parameters @a and @b as simply as possible
}

# I would like to call two_array_sum here and pass two arrays, @c and @d

Web からいくつかの例を見て試してみましたが、どれもうまくいきませんでした。

4

7 に答える 7

29

これを行うには、次の 2 つの方法があります。

  1. 試作品による
  2. 参照により

しかし、これらについて議論する前に、あなたが質問で示したことがあなたがやりたいことの範囲に関するものである場合は、提案させてくださいList::MoreUtils::pairwise

したがって、これをどこに書くか:

my @sum = two_array_sum( @a, @b )

あなたは単にこれを書くでしょう:

my @sum = pairwise { $a + $b } @a, @b;

試作品による

これは のように機能しpushます。(そして、何かにシジルをpush要求するのと同じように)@

sub two_array_sub (\@\@) { 
    my ( $aref, $bref ) = @_;
    ...
}

こうするとこうなる

two_array_sub( @a, @b );

できます。通常は、1 つの長いリストとしてサブに表示されます。以下の私の議論でわかるように、それらは万人向けではありません。

参照により

それは、誰もがあなたに示している方法です。

some_sub( \@a, \@b );

試作品について

彼らは気難しいです。参照がある場合、これは機能しません:

two_array_sub( $arr_ref, $brr_ref );

次のように渡す必要があります。

two_array_sub( @$arr_ref, @$brr_ref );

ただし、「配列式」を作成すると、配列が深くネストされて非常に見苦しくなります。そのため、Perl が取得する参照の型を「文字クラス」構造に配置することでオーバーロードできるため、Perl の煩わしさを避けることがよくあります。\[$@]参照がスカラーまたは配列のいずれかになる可能性があることを意味します。

sub new_two_array_sub (\[$@]\[$@]) { 
    my $ref = shift;
    my $arr = ref( $ref ) eq 'ARRAY' ? $ref : $$ref; # ref -> 'REF';
    $ref    = shift;
    my $brr = ref( $ref ) eq 'ARRAY' ? $ref : $$ref;
    ...
}

したがって、これらはすべて機能します。

new_two_array_sub( @a, $self->{a_level}{an_array} );
new_two_array_sub( $arr, @b );
new_two_array_sub( @a, @b );
new_two_array_sub( $arr, $self->{a_level}{an_array} );

しかし、Perl はまだこれにうるさいです... 何らかの理由で:

new_two_array_sub( \@a, $b );
OR 
new_two_array_sub( $a, [ 1..3 ] );

または、配列への参照として表示される可能性のあるその他の「コンストラクター」。幸いなことに、古いPerl 4では Perl を黙らせることができます。 &

&new_two_array_sub( \@a, [ 1..3 ] );

次に、サブルーチンの多重化コードが 2 つの配列参照を処理します。

于 2011-04-15T19:00:26.890 に答える
7

配列への参照を関数に渡します。

two_array_sum( \@a, \@b )

andは特別な (ソート用)ため、 aorbを変数名として使用しないでください。$a$b

于 2011-04-15T17:18:50.167 に答える
6

から引用しますman perlrefが、すべて読む必要があります。

   Making References

   References can be created in several ways.

   1.  By using the backslash operator on a variable, subroutine, or
       value.  (This works much like the & (address-of) operator in C.)
       This typically creates another reference to a variable, because
       there's already a reference to the variable in the symbol table.
       But the symbol table reference might go away, and you'll still have
       the reference that the backslash returned.  Here are some examples:

           $scalarref = \$foo;
           $arrayref  = \@ARGV;
           $hashref   = \%ENV;
           $coderef   = \&handler;
           $globref   = \*foo;

...

   Using References

   That's it for creating references.  By now you're probably dying to
   know how to use references to get back to your long-lost data.  There
   are several basic methods.

   1.  Anywhere you'd put an identifier (or chain of identifiers) as part
       of a variable or subroutine name, you can replace the identifier
       with a simple scalar variable containing a reference of the correct
       type:

           $bar = $$scalarref;
           push(@$arrayref, $filename);
           $$arrayref[0] = "January";
           $$hashref{"KEY"} = "VALUE";
           &$coderef(1,2,3);
           print $globref "output\n";
于 2011-04-15T17:18:07.233 に答える
4
my @sums = two_array_sum(\@aArray, \@bArray);

sub two_array_sum { # two_array_sum ( (1 2 3 4), (2, 4, 0, 1) ) -> (3, 6, 3, 5)
    my ($aRef, $bRef) = @_;
    my @result = ();

    my $idx = 0;
    foreach my $aItem (@{$aRef}) {
        my $bItem = $bRef->[$idx++];
        push (@result, $aItem + $bItem);
    }

    return @result;
}
于 2011-04-15T17:20:06.777 に答える
3

配列を関数に渡すことはできません。関数は、引数のスカラーのリストのみを受け入れることができます。そのため、配列を再作成するのに十分なデータを提供するスカラーを渡す必要があります。

そのための最も簡単な方法は、配列への参照を渡すことです。

sub two_array_sum {
   my ($array0, $array1) = @_;

   my @array0 = @$array0;
   my @array1 = @$array1;

   return map { $array0[$_] + $array1[$_] } 0..$#array0;
}

配列の再構築を回避し、参照を直接操作することもできます。

sub two_array_sum {
   my ($array0, $array1) = @_;
   return map { $array0->[$_] + $array1->[$_] } 0..$#$array0;
}

使用法:

my @array0 = (1, 2, 3, 4);
my @array1 = (2, 4, 0, 1);
two_array_sum(\@array0, \@array1);

角かっこは、匿名配列(内の式の結果が入力されます)を構成し、その配列への参照を返します。したがって、上記は次のように書くこともできます。

two_array_sum([1, 2, 3, 4], [2, 4, 0, 1]);
于 2011-04-15T18:59:01.587 に答える
2

参照を使用して、配列またはハッシュをサブルーチンに渡す必要があります。例:

sub two_array_sum {
  my ($x, $y) = @_;
  #process $x, $y;
}
two_array_sum(\@a, \@b);
于 2011-04-15T17:20:22.167 に答える
0

これらの方法は標準的です。それを行う別の方法:

use strict;
my $data;

@{$data->{array1}} = qw(foo bar baz);
@{$data->{array2}} = qw(works for me);
testsub($data);

sub testsub
{
    my ($data) = @_;
    print join "\t", @{$data->{array1}}, "\n";
    print join "\t", @{$data->{array2}}, "\n";
    $data->{array1}[3] = "newitem";
    delete $data->{array2};
    push @{$data->{newarray}}, (1, 2, 3);
    return $data;
}

このようにすると、構成情報と混ざり合ったプログラムデータのネズミの巣に悩まされることなく、変数をより厳密に制御できます。

一般に、どのプログラムにも3つまたは4つを超える変数はありません。

私もそれにシステムを維持します-私はリストのハッシュのリストのハッシュを使用します。

$config->{server}[0]{prod}[0]{input}[0] = 'inputfile';

その理由は、それぞれの方法を交互に行うことに一貫性がある限り、Data::Dumper構造全体をダンプでき、データの範囲をより適切に制御でき、構造全体を簡単に渡すことができるためです。

このような複数の構造体をサブルーチンに渡すことがよくあります。スカラーとして、それらは非常にうまく通過します、ありがとう。

于 2011-04-15T18:56:29.587 に答える