Perl で関数にハッシュを渡すにはどうすればよいですか?
-
03-07-2019 - |
質問
変数と連想配列を受け取る関数がありますが、それらを正しく渡すことができないようです。これは関数宣言と関係があると思いますが、Perl で関数宣言がどのように機能するのかわかりません。これに関する適切なリファレンスはありますか?また、必要なことを達成するにはどうすればよいですか?
参照によって渡す必要があることを付け加えておきます。
sub PrintAA
{
my $test = shift;
my %aa = shift;
print $test . "\n";
foreach (keys %aa)
{
print $_ . " : " . $aa{$_} . "\n";
$aa{$_} = $aa{$_} . "+";
}
}
解決
ハッシュ自体の代わりに参照を渡します。
のようにPrintAA("abc", \%fooHash);
sub PrintAA
{
my $test = shift;
my $aaRef = shift;
print $test, "\n";
foreach (keys %{$aaRef})
{
print ハッシュ自体の代わりに参照を渡します。
のように
<*>
perlfaq7も参照してください: {Function、FileHandle、Array、Hash、Method、Regex}を渡す/返すにはどうすればよいですか?
, " : ", $aaRef->{ハッシュ自体の代わりに参照を渡します。
のように
<*>
perlfaq7も参照してください: {Function、FileHandle、Array、Hash、Method、Regex}を渡す/返すにはどうすればよいですか?
}, "\n";
}
}
perlfaq7も参照してください: {Function、FileHandle、Array、Hash、Method、Regex}を渡す/返すにはどうすればよいですか?
他のヒント
このコードは機能します:
#!/bin/perl -w
use strict;
sub PrintAA
{
my($test, %aa) = @_;
print $test . "\n";
foreach (keys %aa)
{
print このコードは機能します:
my $test = shift;
my(%aa) = @_;
重要な点は、関数のmy() 'statement'で配列コンテキストを使用することです。
配列コンテキストビジネスは実際に何をしますか?
簡潔に言うと、正しく動作します。
これは、引数の @_
配列の最初の値が $ test
に割り当てられ、残りの項目がハッシュ%aaに割り当てられることを意味します
。私がそれを呼び出した方法を考えると、 @_
には奇数のアイテムがあるので、最初のアイテムが $ test
に割り当てられると、偶数のアイテムが%aa
に割り当て可能な項目。各ペアの最初の項目はキー(この例では「aaa」、「bbb」、「ccc」)で、2番目は対応する値です。
%aa
を @aa
に置き換えることができます。この場合、配列には6つのアイテムが含まれます。 %aa
を $ aa
に置き換えることもできます。その場合、変数 $ aa
には値「aaa」が含まれます。 、および @_
の残りの値は割り当てによって無視されます。
変数リストの括弧を省略すると、Perlはコードのコンパイルを拒否します。
別の回答の1つは表記法を示しました。
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つの my
ステートメントの後、このバリエーションでは @_
には6つの要素しか含まれないのに対して、単一の my
バージョンでは、 7つの要素が含まれています。
SO 配列コンテキストについて。
実際には、 my($ test、%aa)= @_;について尋ねていませんでした
私は my(%hash)=( 'aaa' =&gtについて尋ねていました; 1、 'bbb' =&gt; 'balls'、 'ccc' =&gt; \&amp; PrintAA);
対 my%hash = {'aaa' =&gt; 1、...};
違いは、{...}表記はハッシュrefを生成し、(...)表記はハッシュ(ハッシュrefではなく)にマッピングされるリストを生成することです。同様に、[...]は配列ではなく配列refを生成します。
実際には、「メイン」コードを次のように変更します。実行時(コンパイル時ではない)エラーが発生します-ファイルに代替コーディングを追加したため、行番号を慎重に扱ってください:
<*> . " : " . $aa{このコードは機能します:
<*>
重要な点は、関数のmy() 'statement'で配列コンテキストを使用することです。
配列コンテキストビジネスは実際に何をしますか?
簡潔に言うと、正しく動作します。
これは、引数の @_
配列の最初の値が $ test
に割り当てられ、残りの項目がハッシュ%aaに割り当てられることを意味します
。私がそれを呼び出した方法を考えると、 @_
には奇数のアイテムがあるので、最初のアイテムが $ test
に割り当てられると、偶数のアイテムが%aa
に割り当て可能な項目。各ペアの最初の項目はキー(この例では「aaa」、「bbb」、「ccc」)で、2番目は対応する値です。
%aa
を @aa
に置き換えることができます。この場合、配列には6つのアイテムが含まれます。 %aa
を $ aa
に置き換えることもできます。その場合、変数 $ aa
には値「aaa」が含まれます。 、および @_
の残りの値は割り当てによって無視されます。
変数リストの括弧を省略すると、Perlはコードのコンパイルを拒否します。
別の回答の1つは表記法を示しました。
<*>
これは、私が書いたものとほとんど同じです。違いは、2つの my
ステートメントの後、このバリエーションでは @_
には6つの要素しか含まれないのに対して、単一の my
バージョンでは、 7つの要素が含まれています。
SO 配列コンテキストについて。
実際には、 my($ test、%aa)= @_;について尋ねていませんでした
私は my(%hash)=( 'aaa' =&gtについて尋ねていました; 1、 'bbb' =&gt; 'balls'、 'ccc' =&gt; \&amp; PrintAA);
対 my%hash = {'aaa' =&gt; 1、...};
違いは、{...}表記はハッシュrefを生成し、(...)表記はハッシュ(ハッシュrefではなく)にマッピングされるリストを生成することです。同様に、[...]は配列ではなく配列refを生成します。
実際には、「メイン」コードを次のように変更します。実行時(コンパイル時ではない)エラーが発生します-ファイルに代替コーディングを追加したため、行番号を慎重に扱ってください:
<*>} . "\n";
}
}
my(%hash) = ( 'aaa' => 1, 'bbb' => 'balls', 'ccc' => \&PrintAA );
PrintAA("test", %hash);
重要な点は、関数のmy() 'statement'で配列コンテキストを使用することです。
配列コンテキストビジネスは実際に何をしますか?
簡潔に言うと、正しく動作します。
これは、引数の @_
配列の最初の値が $ test
に割り当てられ、残りの項目がハッシュ%aaに割り当てられることを意味します
。私がそれを呼び出した方法を考えると、 @_
には奇数のアイテムがあるので、最初のアイテムが $ test
に割り当てられると、偶数のアイテムが%aa
に割り当て可能な項目。各ペアの最初の項目はキー(この例では「aaa」、「bbb」、「ccc」)で、2番目は対応する値です。
%aa
を @aa
に置き換えることができます。この場合、配列には6つのアイテムが含まれます。 %aa
を $ aa
に置き換えることもできます。その場合、変数 $ aa
には値「aaa」が含まれます。 、および @_
の残りの値は割り当てによって無視されます。
変数リストの括弧を省略すると、Perlはコードのコンパイルを拒否します。 別の回答の1つは表記法を示しました。
<*>これは、私が書いたものとほとんど同じです。違いは、2つの my
ステートメントの後、このバリエーションでは @_
には6つの要素しか含まれないのに対して、単一の my
バージョンでは、 7つの要素が含まれています。
SO 配列コンテキストについて。
実際には、
my($ test、%aa)= @_;について尋ねていませんでした
私はmy(%hash)=( 'aaa' =&gtについて尋ねていました; 1、 'bbb' =&gt; 'balls'、 'ccc' =&gt; \&amp; PrintAA);
対my%hash = {'aaa' =&gt; 1、...};
違いは、{...}表記はハッシュrefを生成し、(...)表記はハッシュ(ハッシュrefではなく)にマッピングされるリストを生成することです。同様に、[...]は配列ではなく配列refを生成します。
実際には、「メイン」コードを次のように変更します。実行時(コンパイル時ではない)エラーが発生します-ファイルに代替コーディングを追加したため、行番号を慎重に扱ってください:
<*>別の方法:
sub PrintAA
{
my $test = shift;
my %aa = @_;
print $test . "\n";
foreach (keys %aa)
{
print 別の方法:
<*>
基本的に欠けているのは、連想配列が単一の引数ではないということです(ただし、Paul Tomblinの答えのように、連想配列参照はあります)。
. " : " . $aa{別の方法:
<*>
基本的に欠けているのは、連想配列が単一の引数ではないということです(ただし、Paul Tomblinの答えのように、連想配列参照はあります)。
} . "\n";
$aa{別の方法:
<*>
基本的に欠けているのは、連想配列が単一の引数ではないということです(ただし、Paul Tomblinの答えのように、連想配列参照はあります)。
} = $aa{別の方法:
<*>
基本的に欠けているのは、連想配列が単一の引数ではないということです(ただし、Paul Tomblinの答えのように、連想配列参照はあります)。
} . "+";
}
}
基本的に欠けているのは、連想配列が単一の引数ではないということです(ただし、Paul Tomblinの答えのように、連想配列参照はあります)。
ハッシュへの参照を渡す必要があるようです。
sub PrintAA
{
my $test = shift;
my $aa = shift;
if (ref($aa) != "HASH") { die "bad arg!" }
....
}
PrintAA($foo, \%bar);
できない理由
my %aa = shift;
は、Perlがサブルーチンへのすべての引数を1つのリスト@_にフラット化するためです。すべての要素がコピーされるため、参照渡しではそれらのコピーも回避されます。
いつものように、いくつかの方法があります。最も尊敬される Perlのベストプラクティス スタイルポインター、関数にパラメーターを渡すことについて言わなければならない:
3つ以上のパラメーターを持つサブルーチンには名前付き引数のハッシュを使用します
ただし、2つしかないため、次のように直接渡すことで逃げることができます;)
my $scalar = 5;
my %hash = (a => 1, b => 2, c => 3);
func($scalar, %hash)
そして、関数は次のように定義されます:
sub func {
my $scalar_var = shift;
my %hash_var = @_;
... Do something ...
}
コードを表示できるとさらに便利になる可能性があります。
上記のすべてのメソッドは機能しますが、これは常にこのようなことをすることを好む方法でした:
sub PrintAA ($\%)
{
my $test = shift;
my %aa = ${shift()};
print "$test\n";
foreach (keys %aa)
{
print "上記のすべてのメソッドは機能しますが、これは常にこのようなことをすることを好む方法でした:
PrintAA("test", %hash);
注:コードも少し変更しました。 Perlの二重引用符で囲まれた文字列は、実際の文字列 '$ test'
ではなく、&quot; $ test&quot;
を $ test
の値として解釈します。そんなに多くの。
sは必要ありません。
また、プロトタイプの動作についても間違っていました。ハッシュを渡すには、これを使用します:
PrintAA("test", %$ref_to_hash);
ハッシュリファレンスを出力するには、これを使用します:
<*>
もちろん、コピーを送信しているため $ ref_to_hash
が参照するハッシュを変更することはできませんが、生の%hash
は変更できます参照として渡します。
: $aa{上記のすべてのメソッドは機能しますが、これは常にこのようなことをすることを好む方法でした:
<*>
注:コードも少し変更しました。 Perlの二重引用符で囲まれた文字列は、実際の文字列 '$ test'
ではなく、&quot; $ test&quot;
を $ test
の値として解釈します。そんなに多くの。
sは必要ありません。
また、プロトタイプの動作についても間違っていました。ハッシュを渡すには、これを使用します:
<*>
ハッシュリファレンスを出力するには、これを使用します:
<*>
もちろん、コピーを送信しているため $ ref_to_hash
が参照するハッシュを変更することはできませんが、生の%hash
は変更できます参照として渡します。
}\n";
$aa{上記のすべてのメソッドは機能しますが、これは常にこのようなことをすることを好む方法でした:
<*>
注:コードも少し変更しました。 Perlの二重引用符で囲まれた文字列は、実際の文字列 '$ test'
ではなく、&quot; $ test&quot;
を $ test
の値として解釈します。そんなに多くの。
sは必要ありません。
また、プロトタイプの動作についても間違っていました。ハッシュを渡すには、これを使用します:
<*>
ハッシュリファレンスを出力するには、これを使用します:
<*>
もちろん、コピーを送信しているため $ ref_to_hash
が参照するハッシュを変更することはできませんが、生の%hash
は変更できます参照として渡します。
} = "$aa{上記のすべてのメソッドは機能しますが、これは常にこのようなことをすることを好む方法でした:
<*>
注:コードも少し変更しました。 Perlの二重引用符で囲まれた文字列は、実際の文字列 '$ test'
ではなく、&quot; $ test&quot;
を $ test
の値として解釈します。そんなに多くの。
sは必要ありません。
また、プロトタイプの動作についても間違っていました。ハッシュを渡すには、これを使用します:
<*>
ハッシュリファレンスを出力するには、これを使用します:
<*>
もちろん、コピーを送信しているため $ ref_to_hash
が参照するハッシュを変更することはできませんが、生の%hash
は変更できます参照として渡します。
}+";
}
}
注:コードも少し変更しました。 Perlの二重引用符で囲まれた文字列は、実際の文字列 '$ test'
ではなく、&quot; $ test&quot;
を $ test
の値として解釈します。そんなに多くの。
sは必要ありません。
また、プロトタイプの動作についても間違っていました。ハッシュを渡すには、これを使用します:
<*>ハッシュリファレンスを出力するには、これを使用します:
<*>もちろん、コピーを送信しているため $ ref_to_hash
が参照するハッシュを変更することはできませんが、生の%hash
は変更できます参照として渡します。
関数の引数は、単一の配列(@_)にフラット化されます。そのため、通常はハッシュを参照渡しで関数に渡すのが最も簡単です。
ハッシュを作成するには:
my %myhash = ( key1 => "val1", key2 => "val2" );
そのハッシュへの参照を作成するには:
my $href = \%myhash
参照によってそのハッシュにアクセスするには、
%$href
だからあなたのサブ:
my $myhref = shift;
keys %$myhref;
これまでのところ、ここでの他のすべての返信はかなり複雑に思えます。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 では引数が常にスカラー値の配列として渡され、ハッシュを渡すとそのキー値/ペアがその配列に追加されるため、これが機能します。上記のサンプルでは、引数は配列 (@_
) 実際には次のとおりです。
'!!!', 'abc', 'Hello', 'efg', 'World'
そして '!!!'単純に割り当てられています %string
, 、 その間 %hash
他のすべての引数を「飲み込み」、常に 1 つをキーとして解釈し、次の引数を値として解釈します (すべての要素が使い果たされるまで)。
この方法で複数のハッシュを渡すことはできません。また、ハッシュを最初の引数にすることはできません。そうしないと、すべてが飲み込まれ、他のすべての引数が割り当てられないままになってしまいます。
もちろん、最後の引数としての配列に対してもまったく同じことが機能します。ここでの唯一の違いは、配列ではキーと値が区別されず、残った引数はすべて値であり、配列にプッシュされるだけであることです。
次のサブを使用して、ハッシュまたはhashrefを取得します-渡されたもの:)
sub get_args { ref( 次のサブを使用して、ハッシュまたはhashrefを取得します-渡されたもの:)
printAA($firstarg,somearg=>1, anotherarg=>2)
次のように関数を呼び出します:
printAA($firstarg,{somearg=>1, anotherarg=>2})
またはこのように(問題ではない):
my(%hash) = ( 'aaa' => 1, 'bbb' => 'balls', 'ccc' => \PrintAA );
PrintAA("test", %hash);
またはこのように(問題ではない):
<*>
乾杯!
[0] ) ? shift() : ( @_ % 2 ) ? {} : {@_}; }
sub PrintAA
{
my $test = shift;
my $aa = get_args(@_);;
#then
$aa->{somearg} #do something
$aa->{anotherearg} #do something
}
次のように関数を呼び出します:
<*>またはこのように(問題ではない):
<*>またはこのように(問題ではない):
<*>乾杯!