我看到人们使用两种样式在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' } );
使用 foo()样式而不是 bar()样式有什么好处?
答案 0 :(得分:9)
第二种方法将引用传递给hash,而第一种方法只传递一个列表。
这里有两个方面:从理论上讲,哈希的参考在性能方面可能更好,但对于简短的参数列表,这可以忽略不计。对于像foo(a => 1, b => 2)
这样的简单调用,没有性能差异,因为@_
实际上是原始值的别名。
但是如果调用者已经有哈希值,那么第一种样式需要从哈希转换为列表,然后再转回哈希,这可能很慢。
第二个方面是谁负责转换为哈希的问题。第一种风格将它留给被调用的函数,如果它只是my %args = @_
,如果参数列表的长度不均匀,它将产生好奇的警告。
这就是为什么我稍微偏爱第二种风格(或者我使用Perl 6,它本身支持命名参数)。
答案 1 :(得分:6)
foo(a => 1, b => 2)
样式是模拟命名参数的常用方法。 bar({a => 1, b => 2})
通常仅用于补充(可能是可选的)参数。
对于典型用法,我更喜欢第一种形式。 {}
是额外输入,要读取额外的噪音,如果省略一个或两个大括号,则会产生可能的错误。任何性能差异都可以忽略不计。 (如果不是,则会遇到更大的问题。)另一方面,将参数包装在匿名哈希构造函数中可以帮助您在编译时而不是运行时查找错误。
第二种形式通常与位置论证混合在一起。例如基准做到了这一点:
cmpthese(10000, {
foo => \&foo,
bar => \&bar,
});
当Tk离开{}
时:
my $text = $w->Scrolled('Text', -width => 80, -height => 50);
这通常是一种风格选择。
答案 2 :(得分: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' );
在第一种情况下,你所做的就是传递一个数组。此上下文中的=>
不是您可能认为的哈希键/值指示符。在这种情况下,它只是一个“胖逗号”。
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' } );
在第二种情况下,您将创建一个匿名哈希,并将对该哈希的引用作为该函数的参数传递。
为什么选择一个而不是另一个?在书中,Perl最佳实践,第9章“命名参数”标题下,作者建议在函数有三个以上参数时使用第二种样式。他也更喜欢它,因为它在编译时而不是在运行时捕获了不匹配的参数。