2009-04-29 19 views
32

私は変数と連想配列をとる関数を持っていますが、それらを正しく渡すことはできません。これは関数宣言と関係があると思いますが、Perlでどのように動作するかはわかりません。これについての良い参考資料はありますか?私は必要なものをどのように達成するのですか?どのようにしてPerlの関数にハッシュを渡すのですか?

私はそれを参照渡しする必要があることを追加する必要があります。

sub PrintAA 
{ 
    my $test = shift; 
    my %aa = shift; 
    print $test . "\n"; 
    foreach (keys %aa) 
    { 
     print $_ . " : " . $aa{$_} . "\n"; 
     $aa{$_} = $aa{$_} . "+"; 
    } 
} 
+0

コードを表示できますか? –

+0

私たちに電話番号を教えてもらえますか? –

答えて

60

ハッシュ自体の代わりに参照を渡します。参照してください

PrintAA("abc", \%fooHash); 

sub PrintAA 
{ 
    my $test = shift; 
    my $aaRef = shift; 

    print $test, "\n"; 
    foreach (keys %{$aaRef}) 
    { 
    print $_, " : ", $aaRef->{$_}, "\n"; 
    } 
} 

のようにもperlfaq7: How can I pass/return a {Function, FileHandle, Array, Hash, Method, Regex}?

+0

どのようにしてやるべきかとは思っていませんでしたが、これは最も簡単な方法です。 – rlbond

4

あなたはハッシュへの参照を渡す必要があるように見えます。

sub PrintAA 
{ 
    my $test = shift; 
    my $aa = shift; 
    if (ref($aa) != "HASH") { die "bad arg!" } 
    .... 
} 

PrintAA($foo, \%bar); 

Perlが1つのリストにサブルーチンにすべての引数を平坦化するので、あなたが

my %aa = shift; 

を行うことができない理由は、ある@_。すべての要素がコピーされるので、参照渡しはそれらのコピーも避けます。また

12

:あなたは根本的に欠けている

sub PrintAA 
{ 
    my $test  = shift; 
    my %aa   = @_; 
     print $test . "\n"; 
     foreach (keys %aa) 
     { 
       print $_ . " : " . $aa{$_} . "\n"; 
       $aa{$_} = $aa{$_} . "+"; 
     } 
} 

事が連想配列は、単一の引数(連想配列の参照がポールTomblinの答えのように、ですが)ではないということです。

3

通常通り、いくつかの方法があります。

つ以上のパラメータ

を持つ任意のサブルーチンのためしかし、以来、名前付き引数のハッシュを使用します。ここでは、スタイルのポインタの最も尊敬は、関数にパラメータを渡すについて言いたいことを持っているものをPerl Best Practicesは、あります

my $scalar = 5; 
my %hash = (a => 1, b => 2, c => 3); 

func($scalar, %hash) 

および機能は、次のように定義されています。このように直接渡すと);あなたは逃げることができ、2つだけを持っています

sub func { 
    my $scalar_var = shift; 
    my %hash_var = @_; 

    ... Do something ... 
} 

コードを表示できると便利です。

15

このコードは動作します:

#!/bin/perl -w 

use strict; 

sub PrintAA 
{ 
    my($test, %aa) = @_; 
    print $test . "\n"; 
    foreach (keys %aa) 
    { 
     print $_ . " : " . $aa{$_} . "\n"; 
    } 
} 

my(%hash) = ('aaa' => 1, 'bbb' => 'balls', 'ccc' => \&PrintAA); 

PrintAA("test", %hash); 

キーポイントは、関数の私の()「ステートメント」内の配列コンテキストを使用することです。


配列コンテキストのビジネスが実際に何をしますか?

簡潔に、正常に動作します。

これは、@_の引数の配列の最初の値が$testに割り当てられ、残りのアイテムがハッシュ%aaに割り当てられていることを意味します。私がそれを呼び出すと、@_には奇数個のアイテムがあるので、最初のアイテムが$testに割り当てられると、%aaに割り当てられる偶数のアイテムがあります。各ペアの最初のアイテムはキー(私の例では 'aaa'、 'bbb'、 'ccc')、2番目の値は対応する値です。

%aa@aaに置き換えることができます。その場合、配列には6個の項目があります。 %aa$aaに置き換えることもできます。その場合、変数$aaに値 'aaa'が含まれ、@_の残りの値は割り当てによって無視されます。

変数リストのかっこを省略すると、Perlはコードのコンパイルを拒否します。代替の答えの一つは 表記を示した:

my $test = shift; 
my(%aa) = @_; 

これは私が書いたものとほとんど同じです。相違点は、2つのmyステートメントの後で、@_にはこのバリエーションで6つの要素のみが含まれていますが、単一のmyバージョンではまだ7つの要素が含まれています。

SOには、配列のコンテキストに関する他の質問があります。実際に、私は差が{...}表記はハッシュリファレンスを生成することである(約my(%hash) = ('aaa' => 1, 'bbb' => 'balls', 'ccc' => \&PrintAA);

my %hash = { 'aaa' => 1, ... };

を求めたmy($test, %aa) = @_;について尋ねなかった


...)表記法はリストを生成します。リストはハッシュにマッピングされます(ハッシュリファレンスとは対照的に)。同様に、[...]は配列ではなく配列refを生成します。

実際には、「メイン」コードを次のように変更します。my(%hash)= {...};

Reference found where even-sized list expected at xx.pl line 18. 
... 
Use of uninitialized value in concatenation (.) or string at xx.pl line 13. 
+2

TMTOWTDIですが、私はこのアプローチを好んでいます。 – spoulson

+0

アレイコンテキストビジネスは実際に何をしていますか? –

+0

実際には、私は my($ test、%aa)= @ _;を質問していませんでした。 私は(%aha => 1、 'bbb' => 'ボール'、 'ccc' => \&PrintAA)私の質問をしていました。 対 my%hash = {'aaa' => 1、...}; –

3

すべての上記の方法が動作しますが、これはいつもの方法だった:私は私のファイルに代替コーディングを追加しましたので、注意して扱うの行番号 - あなたは、実行時(ただし、時間をコンパイルしません)エラーが出ます私はこのようなことを行うことが好ましい:

sub PrintAA ($\%) 
{ 
    my $test  = shift; 
    my %aa   = ${shift()}; 
    print "$test\n"; 
    foreach (keys %aa) 
    { 
     print "$_ : $aa{$_}\n"; 
     $aa{$_} = "$aa{$_}+"; 
    } 
} 

注:私はまた少しあなたのコードを変更しました。 Perlの二重引用符で囲まれた文字列では、実際の文字列'$test'ではなく、が表示されます。.はそれほど必要ありません。

また、プロトタイプの仕組みについては間違っていました。ハッシュを渡すには、これを使用する:

PrintAA("test", %hash); 

をハッシュリファレンスを印刷するには、これを使用する:もちろん

PrintAA("test", %$ref_to_hash); 

、あなたが送っているので、今あなたが$ref_to_hashが参照するハッシュを変更することはできませんコピーを作成することができますが、生の%hashは参照として渡すので修正できます。

+0

1)このコードはうまくいかず、2)Perlのプロトタイプは、ほとんどの人(あなたを含むと思われる人)が期待していることをしないためです。彼らはビルトイン関数の動作をエミュレートするのには適していますが、そうでなければあまり使用しません。プロトタイプの "\%"部分は、第2引数がハッシュであり、それを参照渡しする必要があることを示しています。それは実数*ハッシュでなければなりません。ハッシュリファレンス、またはキー=>値のペアのリストにすることはできません。 –

+0

訂正ありがとうございます。 \%を参照にすることはできませんが、それは当てはまりません。私は彼の関数がパラメータとして渡すハッシュを変更しているようだが、他の点は有効であるので、彼はkey => valueのペアのリストを渡すとは思わない。 –

0

使用folowingサブは、ハッシュまたはハッシュリファレンスを取得する - 渡されたものは何でも:)

sub get_args { ref($_[0]) ? shift() : (@_ % 2) ? {} : {@_}; } 
sub PrintAA 
{ 
    my $test = shift; 
    my $aa = get_args(@_);; 
    #then 
    $aa->{somearg} #do something 
    $aa->{anotherearg} #do something 

} 

は、このようなあなたの関数を呼び出します。

printAA($firstarg,somearg=>1, anotherarg=>2) 

それとも、このように(どんなに):

printAA($firstarg,{somearg=>1, anotherarg=>2}) 

このように(関係なく):

my(%hash) = ('aaa' => 1, 'bbb' => 'balls', 'ccc' => \PrintAA); 

PrintAA("test", %hash); 

乾杯!

+0

プロトタイプを使用すると、サブルーチンの引数をコンパイル時にチェックするだけでなく、同じことを実行できます。さらに、get_argsは一連の参照に惑わされます。 –

+0

ハッシュ(ref)用です:配列ではうまくいかないことがわかります –

+0

@Chrisプロトタイプは、サブルーチンがメソッドとして呼び出されたときに効果がなく、ひどく混乱してしまいます。他の人が以前に投稿したように、組み込みのようなサブ作業をする必要がないかぎり、それらを使用しないでください。 – converter42

1

関数の引数は単一の配列(@_)にフラット化されます。だから、参照によって機能するようにハッシュを渡すのが普通簡単です。そのハッシュへの参照を作成する

my %myhash = (key1 => "val1", key2 => "val2"); 

:HASHを作成する

参照によりそのハッシュにアクセスする

my $href = \%myhash 

と、だからあなたのサブで

%$href 

は:ここ

my $myhref = shift; 

keys %$myhref; 
1

他のすべての返信は、これまでのところ私にはかなり複雑に見えます。 Perl関数を書くとき、私は通常、渡されたすべての引数を関数の最初の行に "展開"します。

sub someFunction { 
    my ($arg1, $arg2, $arg3) = @_; 

これは、あなたが

... someFunction (arg1, arg2, arg3) 

としての機能を宣言し、あなたがそのように行うと、最後の引数としてハッシュを渡す場合、あなたはどんなトリックなしで大丈夫です他の言語に似ています特別な魔法です。例えばは:

sub testFunc { 
    my ($string, %hash) = @_; 
    print "$string $hash{'abc'} $hash{'efg'} $string\n"; 
} 

my %testHash = (
    'abc' => "Hello", 
    'efg' => "World" 
); 
testFunc('!!!', %testHash); 

出力が期待されているとおり

!!! Hello World !!! 

これはPerlの引数でbecausは常にスカラー値の配列として渡されると、あなたはハッシュを渡すと、それはキー値の作品/ペアがありますその配列に追加されます。上記のサンプルでは、​​アレイ(@_)として関数に渡された引数は、実際には次のとおり

'!!!', 'abc', 'Hello', 'efg', 'World' 

と「!'は%stringにシンプルに割り当てられ、%hashは他のすべての引数を "捨て"、常にキーとして解釈し、次の値を(すべての要素が使い尽くされるまで)解釈します。

ハッシュを最初の引数にすることはできません。それ以外の場合はすべてを呑み込み、他のすべての引数は割り当てられません。

もちろん、最後の引数として配列に対して全く同じことが働きます。ここでの唯一の違いは、配列はキーと値を区別しないということです。それらの引数はすべて値であり、配列にプッシュされるからです。

関連する問題