& $ func($ arg)和$ func->($ arg)之间有什么区别吗?

时间:2014-01-12 11:30:29

标签: perl

在尝试理解闭包时,在perl-faq中通过perlrefcoderef阅读了这些示例:

sub add_function_generator {
    return sub { shift() + shift() };
}
my $add_sub = add_function_generator();
my $sum = $add_sub->(4,5);

sub newprint {
    my $x = shift;
    return sub { my $y = shift; print "$x, $y!\n"; };
}
$h = newprint("Howdy");
&$h("world");

这里有两种调用存储在变量中的函数的形式。

&$func($arg)
$func->($arg)

那些是完全等效的(只是语法上不同)还是存在一些差异?

1 个答案:

答案 0 :(得分:13)

没有区别。证明:每个版本生成的操作码:

$ perl -MO=Concise -e'my $func; $func->()'
8  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter ->2
2     <;> nextstate(main 1 -e:1) v:{ ->3
3     <0> padsv[$func:1,2] vM/LVINTRO ->4
4     <;> nextstate(main 2 -e:1) v:{ ->5
7     <1> entersub[t2] vKS/TARG ->8
-        <1> ex-list K ->7
5           <0> pushmark s ->6           
-           <1> ex-rv2cv K ->-           
6              <0> padsv[$func:1,2] s ->7
$ perl -MO=Concise -e'my $func; &$func()'
8  <@> leave[1 ref] vKP/REFC ->(end)     
1     <0> enter ->2                      
2     <;> nextstate(main 1 -e:1) v:{ ->3 
3     <0> padsv[$func:1,2] vM/LVINTRO ->4
4     <;> nextstate(main 2 -e:1) v:{ ->5 
7     <1> entersub[t2] vKS/TARG ->8      
-        <1> ex-list K ->7               
5           <0> pushmark s ->6           
-           <1> ex-rv2cv sKPRMS/4 ->-    
6              <0> padsv[$func:1,2] s ->7

...等等,- <1> ex-rv2cv sKPRMS/4 ->-的标志实际上略有不同。无论如何,它们似乎并不重要,两种形式都表现相同。

但我建议使用$func->()形式:我认为这种语法更优雅,你不会忘记使用parens(&$func有效,但会使当前{{1}对函数可见,这不是你通常想要的。)