web-dev-qa-db-ja.com

ハッシュをサブルーチンに渡すにはどうすればよいですか?

これを行う方法を理解する助けが必要です。私のコード:

my %hash;
$hash{'1'}= {'Make' => 'Toyota','Color' => 'Red',};
$hash{'2'}= {'Make' => 'Ford','Color' => 'Blue',};
$hash{'3'}= {'Make' => 'Honda','Color' => 'Yellow',};


&printInfo(%hash);

sub printInfo{
   my (%hash) = %_;
   foreach my $key (keys %_{       
    my $a = $_{$key}{'Make'};   
    my $b = $_{$key}{'Color'};   
    print "$a $b\n";
    }
}
20
nebulus

コードが進化するときに問題を引き起こす可能性のある簡単な方法は、デフォルトの配列@_(すべてのキーと値のペアを偶数リストとして含む)を%hashに割り当てることです。したがって、コードは次のようになります。

sub printInfo {
   my %hash = @_;
   ...
}

より良い方法は、サブルーチンへの参照としてハッシュを渡すことです。このようにして、サブルーチンにさらに多くのパラメーターを渡すことができます。

printInfo(\%hash);
sub PrintInfo {
   my %hash = %{$_[0]};
   ...
}

Perlで参照を使用する方法の概要は、 perlreftut にあります

33
ghandi

あなたはとてもとても、とても近くにいます。ハッシュを渡すための%_はありません。@_で渡す必要があります。幸い、ハッシュはリストコンテキストを使用して割り当てられるため、

sub printInfo {
   my %hash = @_;
   ...
}

それを動作させます!

また、サブルーチン呼び出しの前に&を使用することは、少なくともPerl 5.000以降、ほとんどの場合不要です。最近は他の言語と同じように、名前と引数だけでPerlサブルーチンを呼び出すことができます。 (@mobがコメントで指摘しているように、これが依然として必要な場合があります。これについて詳しく知りたい場合は perlsub を参照してください。)

8
Robert P

あなたが欲しいと思う

_my %hash;
$hash{'1'}= {'Make' => 'Toyota','Color' => 'Red',};
$hash{'2'}= {'Make' => 'Ford','Color' => 'Blue',};
$hash{'3'}= {'Make' => 'Honda','Color' => 'Yellow',};

printInfo(%hash);

sub printInfo{
   my %hash = @_;
   foreach my $key (keys %hash){       
    my $a = $hash{$key}{'Make'};   
    my $b = $hash{$key}{'Color'};   
    print "$a $b\n";
   }
}
_

printInfo(%hash)で、_%hash_は、交互のキーと値のペアを持つリストに展開されます。

printInfoでは、_@__がこのリストであり、_%hash_に割り当てられると、リスト内の交互の要素から対応する値を持つキーが再度作成されます。

6

ハッシュと配列を渡す最良の方法は reference です。参照は、複雑なデータ構造を単一のデータポイントとして説明するための方法です-スカラー変数に格納できるもの($fooなど)。

references を読んで、元のデータに戻すために参照とdereference参照を作成する方法を理解します。

基本:データ構造の前にバックスラッシュを付けて、その構造への参照を取得します。

my $hash_ref   = \%hash;
my $array_ref  = \@array;
my $scalar_ref = \$scalar;   #Legal, but doesn't do much for you...

参照とは、元の構造のメモリの場所(および構造に関する手掛かり)です。

print "$hash_ref\n";

次のようなものを印刷します:

HASH(0x7f9b0a843708)

参照を使用可能な形式に戻すには、参照を正しい sigil の前に置くだけです。

my %new_hash = %{ $hash_ref };

これは、Perlで非常に複雑なデータ構造を作成する方法であり、オブジェクト指向のPerlが機能する方法であるため、参照の使用について学ぶ必要があります。


3つのハッシュをサブルーチンに渡したいとしましょう。ここに3つのハッシュがあります:

my %hash1 = ( this => 1, that => 2, the => 3, other => 4 );
my %hash2 = ( tom => 10, dick => 20, harry => 30 );
my %hash3 = ( no => 100, man => 200, is => 300, an => 400, island => 500 );

それらの参照を作成します

my $hash_ref1 = \%hash1;
my $hash_ref2 = \%hash2;
my $hash_ref3 = \%hash3;

そして今、参照を渡すだけです:

mysub ( $hash_ref1, $hash_ref2, $hash_ref3 );

参照はscalarデータなので、これらを私のサブルーチンに渡しても問題はありません。

sub mysub {
    my $sub_hash_ref1  = shift;
    my $sub_hash_ref2  = shift;
    my $sub_hash_ref3  = shift;

今、私はそれらを逆参照するだけで、私のサブルーチンはそれらを使用できます。

    my %sub_hash1 = %{ $sub_hash_ref1 };
    my %sub_hash2 = %{ $sub_hash_ref2 };
    my %sub_hash3 = %{ $sub_hash_ref3 };

ref コマンドを使用すると、参照が参照先であることがわかります。

my $ref_type = ref $sub_hash_ref;    # $ref_type is now equal to "HASH"

これは、正しいタイプのデータ構造が渡されていることを確認したい場合に便利です。

sub mysub {
    my $hash_ref = shift;

    if ( ref $hash_ref ne "HASH" ) {
        croak qq(You need to pass in a hash reference);
    }

また、これらはメモリ参照であるため、参照を変更すると元のハッシュも変更されることに注意してください。

my %hash = (this => 1, is => 2, a => 3 test => 4);
print "$hash{test}\n";   # Printing "4" as expected
sub mysub ( \%hash );    # Passing the reference
print "$hash{test}\n";   # This is printing "foo". See subroutine:


sub mysub { 
    my $hash_ref = shift;

    $hash_ref->{test} = "foo";    This is modifying the original hash!
}

これは良いことかもしれません-それはあなたがサブルーチンに渡されたデータを修正することを可能にします、あるいは悪い-それはあなたが意図せずに元のサブルーチンに渡されたデータを修正することを可能にします。

5
David W.

あなたはそれらを渡すことができます

  1. 引数リストdo_hash_thing( %hash )
  2. 引数リストのハッシュへの参照 `do_hash_thing(@args_before、\%hash、@args_after)
  3. prototypeによる参照として、keysおよびその他のハッシュ演算子のように機能します。

リストは次のように機能します。

sub do_hash_thing {
    my %hash = @_;
    ...
}

do_hash_thing( %hash );

これにより、ハッシュ引数を「ストリーミング」することもできます。

do_hash_thing( %hash_1, %hash_2, parameter => 'green', other => 'pair' );

参照により、次のように機能します。

sub do_hash_thing { 
    my $hash_ref = shift;
    ...
}

do_hash_thing( \%hash, @other_args );

ここでプロトタイプ(\%@)。プロトタイプにより、Perlは最初の引数でハッシュを探し、参照で渡します。

sub do_hash_thing (\%@) { 
    my $hash_ref = shift;
    ...
}

do_hash_thing( %hash => qw(other args) );
# OR
do_hash_thing %hash => qw(other args);

警告:プロトタイプはメソッドでは機能しません。

3
Axeman