我有一个带变量和关联数组的函数,但我似乎无法让它们正确传递。我认为这与函数声明有关,但是我无法弄清楚它们在Perl中是如何工作的。对此有一个很好的参考,我如何实现我的需要?

我应该补充一点,它需要通过引用传递。

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

我有一个带变量和关联数组的函数,但我似乎无法让它们正确传递。我认为这与函数声明有关,但是我无法弄清楚它们在Perl中是如何工作的。对此有一个很好的参考,我如何实现我的需要?

我应该补充一点,它需要通过引用传递。

<*> . " : " . $aa{

我有一个带变量和关联数组的函数,但我似乎无法让它们正确传递。我认为这与函数声明有关,但是我无法弄清楚它们在Perl中是如何工作的。对此有一个很好的参考,我如何实现我的需要?

我应该补充一点,它需要通过引用传递。

<*>} . "\n"; $aa{

我有一个带变量和关联数组的函数,但我似乎无法让它们正确传递。我认为这与函数声明有关,但是我无法弄清楚它们在Perl中是如何工作的。对此有一个很好的参考,我如何实现我的需要?

我应该补充一点,它需要通过引用传递。

<*>} = $aa{

我有一个带变量和关联数组的函数,但我似乎无法让它们正确传递。我认为这与函数声明有关,但是我无法弄清楚它们在Perl中是如何工作的。对此有一个很好的参考,我如何实现我的需要?

我应该补充一点,它需要通过引用传递。

<*>} . "+"; } }
有帮助吗?

解决方案

传递引用而不是哈希本身。如在

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'),第二项是相应的值。

可以用 @aa 替换%aa ,在这种情况下,数组中将包含6个项目。也可以用 $ aa 替换%aa ,在这种情况下,变量 $ aa 将包含值'aaa' , @_ 中的其余值将被赋值忽略。

如果省略变量列表周围的括号,Perl拒绝编译代码。 其中一个替代答案显示了符号:

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.

这几乎与我写的相同;不同之处在于,在两个 my 语句之后, @_ 在此变体中只包含6个元素,而在单个 my 版本中,它仍然包含7个元素。

SO 关于数组上下文。


  

实际上,我没有询问 my($ test,%aa)= @_; 我问的是 my(%hash)=('aaa'=&gt ; 1,'bbb'=&gt;'球','ccc'=&gt; \&amp; PrintAA); my%hash = {'aaa'=&gt; 1,...};

不同之处在于{...}表示法生成散列引用,而(...)表示法生成一个列表,该列表映射到散列(而不是散列引用)。同样,[...]生成一个数组引用,而不是一个数组。

确实,更改“主要”代码,使其显示为:my(%hash)= {...};并且你得到一个运行时(但不是编译时)错误 - 谨慎对待行号,因为我已经在我的文件中添加了替代编码:

<*> . " : " . $aa{

此代码有效:

<*>

关键是在函数中my()'statement'中使用数组上下文。


  

数组上下文业务实际上做了什么?

简洁地说,它使它正常工作。

这意味着 @_ 参数数组中的第一个值分配给 $ test ,其余项目分配给散列%aa 。鉴于我调用它的方式, @_ 中有一些奇数项,所以一旦将第一项分配给 $ test ,就会有一个偶数个可用于分配给%aa 的项目,每对中的第一项是键(在我的示例中为'aaa','bbb','ccc'),第二项是相应的值。

可以用 @aa 替换%aa ,在这种情况下,数组中将包含6个项目。也可以用 $ aa 替换%aa ,在这种情况下,变量 $ aa 将包含值'aaa' , @_ 中的其余值将被赋值忽略。

如果省略变量列表周围的括号,Perl拒绝编译代码。 其中一个替代答案显示了符号:

<*>

这几乎与我写的相同;不同之处在于,在两个 my 语句之后, @_ 在此变体中只包含6个元素,而在单个 my 版本中,它仍然包含7个元素。

SO 关于数组上下文。


  

实际上,我没有询问 my($ test,%aa)= @_; 我问的是 my(%hash)=('aaa'=&gt ; 1,'bbb'=&gt;'球','ccc'=&gt; \&amp; PrintAA); my%hash = {'aaa'=&gt; 1,...};

不同之处在于{...}表示法生成散列引用,而(...)表示法生成一个列表,该列表映射到散列(而不是散列引用)。同样,[...]生成一个数组引用,而不是一个数组。

确实,更改“主要”代码,使其显示为:my(%hash)= {...};并且你得到一个运行时(但不是编译时)错误 - 谨慎对待行号,因为我已经在我的文件中添加了替代编码:

<*>} . "\n"; } } my(%hash) = ( 'aaa' => 1, 'bbb' => 'balls', 'ccc' => \&PrintAA ); PrintAA("test", %hash);

关键是在函数中my()'statement'中使用数组上下文。


  

数组上下文业务实际上做了什么?

简洁地说,它使它正常工作。

这意味着 @_ 参数数组中的第一个值分配给 $ test ,其余项目分配给散列%aa 。鉴于我调用它的方式, @_ 中有一些奇数项,所以一旦将第一项分配给 $ test ,就会有一个偶数个可用于分配给%aa 的项目,每对中的第一项是键(在我的示例中为'aaa','bbb','ccc'),第二项是相应的值。

可以用 @aa 替换%aa ,在这种情况下,数组中将包含6个项目。也可以用 $ aa 替换%aa ,在这种情况下,变量 $ aa 将包含值'aaa' , @_ 中的其余值将被赋值忽略。

如果省略变量列表周围的括号,Perl拒绝编译代码。 其中一个替代答案显示了符号:

<*>

这几乎与我写的相同;不同之处在于,在两个 my 语句之后, @_ 在此变体中只包含6个元素,而在单个 my 版本中,它仍然包含7个元素。

SO 关于数组上下文。


  

实际上,我没有询问 my($ test,%aa)= @_; 我问的是 my(%hash)=('aaa'=&gt ; 1,'bbb'=&gt;'球','ccc'=&gt; \&amp; PrintAA); my%hash = {'aaa'=&gt; 1,...};

不同之处在于{...}表示法生成散列引用,而(...)表示法生成一个列表,该列表映射到散列(而不是散列引用)。同样,[...]生成一个数组引用,而不是一个数组。

确实,更改“主要”代码,使其显示为:my(%hash)= {...};并且你得到一个运行时(但不是编译时)错误 - 谨慎对待行号,因为我已经在我的文件中添加了替代编码:

<*>

可替换地:

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将子例程的所有参数展平为一个列表@_。每个元素都被复制,因此通过引用传入也可以避免这些副本。

像往常一样,有几种方法。以下是最受尊敬的 Perl最佳实践 样式指针,不得不说将参数传递给函数:

对任何具有三个以上参数的子例程使用命名参数的哈希

但是因为你只有两个,你可以逃脱;)直接传递它们:

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的双引号字符串将&quot; $ test&quot; 解释为 $ test 的值,而不是实际的字符串'$ test',所以你不需要那么多 s。

另外,我对原型的工作方式错了。要传递哈希,请使用:

PrintAA("test", %$ref_to_hash);

要打印哈希引用,请使用:

<*>

当然,现在你无法修改 $ ref_to_hash 引用的哈希,因为你正在发送一个副本,但你可以修改原始的%hash ,因为你把它作为参考传递。

: $aa{

所有上述方法都有效,但这总是我喜欢这样做的方式:

<*>

注意:我也改变了你的代码。 Perl的双引号字符串将&quot; $ test&quot; 解释为 $ test 的值,而不是实际的字符串'$ test',所以你不需要那么多 s。

另外,我对原型的工作方式错了。要传递哈希,请使用:

<*>

要打印哈希引用,请使用:

<*>

当然,现在你无法修改 $ ref_to_hash 引用的哈希,因为你正在发送一个副本,但你可以修改原始的%hash ,因为你把它作为参考传递。

}\n"; $aa{

所有上述方法都有效,但这总是我喜欢这样做的方式:

<*>

注意:我也改变了你的代码。 Perl的双引号字符串将&quot; $ test&quot; 解释为 $ test 的值,而不是实际的字符串'$ test',所以你不需要那么多 s。

另外,我对原型的工作方式错了。要传递哈希,请使用:

<*>

要打印哈希引用,请使用:

<*>

当然,现在你无法修改 $ ref_to_hash 引用的哈希,因为你正在发送一个副本,但你可以修改原始的%hash ,因为你把它作为参考传递。

} = "$aa{

所有上述方法都有效,但这总是我喜欢这样做的方式:

<*>

注意:我也改变了你的代码。 Perl的双引号字符串将&quot; $ test&quot; 解释为 $ test 的值,而不是实际的字符串'$ test',所以你不需要那么多 s。

另外,我对原型的工作方式错了。要传递哈希,请使用:

<*>

要打印哈希引用,请使用:

<*>

当然,现在你无法修改 $ ref_to_hash 引用的哈希,因为你正在发送一个副本,但你可以修改原始的%hash ,因为你把它作为参考传递。

}+"; } }

注意:我也改变了你的代码。 Perl的双引号字符串将&quot; $ test&quot; 解释为 $ test 的值,而不是实际的字符串'$ test',所以你不需要那么多 s。

另外,我对原型的工作方式错了。要传递哈希,请使用:

<*>

要打印哈希引用,请使用:

<*>

当然,现在你无法修改 $ ref_to_hash 引用的哈希,因为你正在发送一个副本,但你可以修改原始的%hash ,因为你把它作为参考传递。

将函数的参数展平为单个数组(@_)。因此,通过引用传递哈希值通常是最容易的。

创建HASH:

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

创建对该HASH的引用:

my $href = \%myhash

通过引用访问该哈希;

%$href

所以在你的潜艇中:

my $myhref = shift;

keys %$myhref;

到目前为止,所有其他回复对我来说都相当复杂。当我写Perl函数时,我通常会“展开”。函数第一行中传递的所有参数。

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

这与其他语言类似,您将函数声明为

... someFunction ( arg1, arg2, arg3 )

如果你这样做并将哈希作为最后一个参数传递,你将没有任何技巧或特殊魔法。 E.g:

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 &quot; swallows&quot;所有其他参数,总是将一个解释为一个键,将下一个解释为值(直到所有元素都用完为止)。

你不能以这种方式传递多个哈希,并且哈希不能是第一个参数,否则它会吞下所有内容并使所有其他参数保持未分配状态。

当然,数组与最后一个参数完全相同。这里唯一的区别是数组不区分键和值,因为剩下的所有参数都是值,只是被推送到数组。

使用下面的sub来获取hash或hashref - 无论传递什么:)

sub get_args { ref( 

使用下面的sub来获取hash或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 }

按照以下方式调用您的函数:

<*>

或者像这样(不管):

<*>

或者甚至喜欢这样(不管):

<*>

干杯!

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top