2010-07-30 49 views
6

我使用人两种风格在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' }); 

什么是使用FOO()风格,而不是巴()风格优势?

回答

9

第二种方法将引用传递给哈希,而第一种方法只传递一个列表。

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

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

第二个方面是谁负责转换为散列的问题。第一种风格将其称为被调用的函数,如果这只是my %args = @_,它将产生奇怪的警告,如果参数列表不是偶数的长度。

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

+1

+1表示性能方面。 – 2010-07-30 13:09:23

+1

这些“性能方面”是不必要的微观优化,不会产生实际好处。散列可以像清单一样容易地使用:'foo(%hash)'或者hashref:'foo(%{$ hashref})'。坚持foo风格给用户留下更多的权力。 – jmz 2010-07-30 13:42:47

+0

实际上,我自己的基准测试显示(在多个安装中)通过列表比引用更快 - 尽管* return *引用似乎更快。 – Axeman 2010-07-30 14:02:12

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章标题为“命名参数”,作者建议在函数有三个以上参数时使用第二种样式。他还喜欢它,因为它在编译时捕获不匹配的参数数量,而不是在运行时。

+3

这是一段时间,因为我读了它,但我认为建议使用3 +参数的hashref而不是一个标准的未命名参数列表,即调用'foo('a','b')',而不是在散列上推荐hashrefs – plusplus 2010-07-30 11:09:22

+3

@plusplus:该部分的标题是:“对于具有三个以上论题的任何子例程,使用命名参数的散列”。在这篇文章的主体中,他特别说过要使用哈希引用来替换转换为哈希的原始名称/值对。 – 2010-07-30 13:06:28

+0

+1用于指定您的参考。 – 2010-07-30 16:03:42

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); 

它通常是一个风格上的选择。