参数在Perl中传递样式

How*_*ard 6 parameters perl

我看到人们使用两种样式在Perl中传递命名参数:

use strict;
use warnings;
use Data::Dumper;

sub foo {
    print Dumper @_;
}

sub bar {
    print Dumper @_;
}

foo( A => 'a', B => 'b' );
bar( { A => 'a', B => 'b' } );
Run Code Online (Sandbox Code Playgroud)

使用foo()样式而不是bar()样式有什么好处?

mor*_*itz 9

第二种方法将引用传递给hash,而第一种方法只传递一个列表.

这里有两个方面:理论上,哈希的引用在性能方面可能更好,但对于简短的参数列表,这可以忽略不计.对于简单的调用,就像foo(a => 1, b => 2)没有性能差异一样,因为@_它实际上是原始值的别名.

但是如果调用者已经在散列中具有值,则第一种样式需要从散列转换为列表,然后再返回到散列,这可能很慢.

第二个方面是谁负责转换为哈希的问题.第一种风格将它调用为被调用的函数,如果只是这样my %args = @_,如果参数列表的长度不均匀,它将产生好奇的警告.

这就是为什么我稍微偏爱第二种风格(或者我使用Perl 6,它本身支持命名参数).


Mic*_*man 6

foo(a => 1, b => 2)风格是模仿命名参数的常用方法.在bar({a => 1, b => 2})通常仅用于补充(也可能是可选的)参数.

对于典型用法,我更喜欢第一种形式.这{}是额外的输入,要读取的额外噪音,如果省略一个或两个大括号,则会产生可能的错误.任何性能差异都可以忽略不计.(如果不是,则会遇到更大的问题.)另一方面,将参数包装在匿名哈希构造函数中可以帮助您在编译时而不是运行时查找错误.

第二种形式通常与位置参数混合在一起.例如Benchmark这样做:

cmpthese(10000, {
    foo => \&foo,
    bar => \&bar,
});
Run Code Online (Sandbox Code Playgroud)

虽然Tk离开{}了:

my $text = $w->Scrolled('Text', -width => 80, -height => 50);
Run Code Online (Sandbox Code Playgroud)

这通常是一种风格选择.


Rob*_*nes 5

首先,解释两种方法:

sub foo {
    # Transform the array to a hash
    my %args = @_;

    foreach my $key ( keys %args ) {
        print "$key => $args{$key}\n";
    }
}

# Pass an array of values
foo( A=>'a', B=>'b' );
Run Code Online (Sandbox Code Playgroud)

在第一种情况下,你所做的就是传递一个数组.该=>在这方面是不是,你可能会认为哈希键/值指标.在这种情况下,它只是一个"胖逗号".

sub bar {
    my ($hash_ref) = @_;
    foreach my $key ( keys %$hash_ref ) {
        print "$key => $hash_ref->{$key}\n";
    }
}

# pass a ref to an anonymous hash
bar( { A=>'a', B=>'b' } );
Run Code Online (Sandbox Code Playgroud)

在第二种情况下,您将创建一个匿名哈希,并将对该哈希的引用作为该函数的参数传递.

为什么选择一个而不是另一个?在书中,Perl最佳实践,第9章"命名参数"标题下,作者建议在函数有三个以上参数时使用第二种样式.他也更喜欢它,因为它在编译时而不是在运行时捕获了不匹配的参数.

  • 我读了它已经有一段时间,但我认为建议使用带有3个以上参数的hashref而不是标准的未命名参数列表,即调用`foo('a','b')`而不是推荐hashrefs哈希 (3认同)
  • @plusplus:该部分的标题是:"对任何具有三个以上争论的子程序使用命名争论的散列." 在这篇文章的正文中,他特别指出使用哈希引用转换为哈希的原始名称/值对. (3认同)