什么时候应该使用&来调用一个Perl子程序?

我听说,人们不应该使用&来调用Perl subs,即:

 function($a,$b,...); # opposed to &function($a,$b,...); 

我知道一个参数列表变成可选的,但是有些情况下适合使用&和你绝对不应该使用的情况?

另外,如果省略“ & ”,那么性能增加如何发挥作用?

国际海事组织,唯一一次有任何理由使用&是如果你正在获取或调用coderef,如:

 sub foo() { print "hi\n"; } my $x = \&foo; &$x(); 

在大多数情况下, 绝对不应该使用它的主要时间是调用具有指定任何非默认调用行为的原型的子。 我的意思是,一些原型允许重新解释参数列表,例如将@array%hash规范转换为引用。 所以这个小组会期待那些重新解释的发生,除非你用手去模仿它们,否则这个小组将得到与预期大不相同的input。

我认为主要是人们试图告诉你,你仍然在用Perl 4编写风格,现在我们有一个更清洁,更好的东西叫Perl 5。

关于性能,Perl有多种方式优化子调用,其中一个主要是常量内联。

还有一种情况是使用&提供性能优势:如果您使用foo(@_)转发子呼叫。 使用&foo的速度比foo(@_)快得多。 我不会推荐它,除非你明确地发现你需要微观优化。

我经常使用& ,但主要是因为我在做怪异的界面。 如果您不需要这些情况之一,请不要使用& 。 其中大部分只是访问一个子程序定义,而不是调用一个子程序。 这一切都在perlsub 。

  1. 参考一个命名的子程序。 对于大多数Perler来说,这可能是唯一的常见情况:

      my $sub = \&foo; 
  2. 同样,分配给一个typeglob,它允许你以不同的名字调用子程序:

      *bar = \&foo; 
  3. 检查是否定义了一个子例程,就像在testing套件中那样:

      if( defined &foo ) { ... } 
  4. 删除一个不常见的子程序定义:

      undef &foo; 
  5. 提供一个调度程序子程序,其唯一的工作是select正确的子程序来调用。 这是我使用& 调用一个子程序的唯一情况,当我期望多次调用调度程序并需要从操作中挤出一点性能时:

      sub figure_it_out_for_me { # all of these re-use the current @_ if( ...some condition... ) { &foo } elsif( ...some other... ) { &bar } else { &default } } 
  6. 要使用当前参数堆栈跳转到另一个子例程(并replace调用堆栈中的当前子例程),请在调度中使用unrare操作,特别是在AUTOLOAD

      goto ⊂ 
  7. 调用一个在内置Perl之后命名的子例程。 &总是给你用户定义的一个。 这就是为什么我们在学习Perl中教它 。 你不是真的想这样做,但它是&的特点之一。

有一些地方你可以使用它们,但有更好的方法:

  1. 调用与内置Perl相同名称的子例程。 只是没有与内置Perl相同名称的子程序。 检查perlfunc以查看不应使用的内置名称列表。

  2. 禁用原型。 如果您不知道这意味着什么,或者您为什么要这样做,请不要使用& 。 一些黑魔法代码可能需要它,但在这种情况下,你可能知道你在做什么。

  3. 取消引用并执行子例程引用。 只需使用->符号。

&子例程()窗体禁用原型检查。 这可能是也可能不是你想要的。

http://www.perl.com/doc/manual/html/pod/perlsub.html#Prototypes

原型允许您指定子程序参数的数量和types,并在编译时检查它们。 这可以提供有用的诊断帮助。

原型不适用于方法调用,或者使用&前缀调用老式风格的调用。

&是引用或取消引用子程序或代码引用所必需的

例如

 sub foo { # a subroutine } my $subref = \&foo; # take a reference to the subroutine &$subref(@args); # make a subroutine call using the reference. my $anon_func = sub { ... }; # anonymous code reference &$anon_func(); # called like this 

原型不适用于子程序引用。

&子程序的forms也被用于所谓的魔法转换forms。

expression式goto &subroutine用当前值@_replace当前的调用上下文,调用指定的子程序。

实质上,您可以通过调用指定的函数将呼叫完全切换到一个子例程。 这在AUTOLOAD块中很常见,在那里可以进行延迟子程序调用,可能对@_做了一些修改,但是它完全看起来像是对指定子的调用。

例如

 sub AUTOLOAD { ... push @_, @extra_args; # add more arguments onto the parameter list goto &subroutine ; # change call another subroutine, as if we were never here } 

}

潜在的,这可能是有用的尾巴呼叫消除 ,我想。

在这里看到这个技巧的详细解释

我读过反对使用'&'的论据,但我几乎总是使用它。 这节省了我太多的时间不去。 我花了很大一部分Perl编码时间来查找代码的哪些部分调用特定的函数。 与领先&,我可以search和立即find他们。 没有领先的&,我得到了函数定义,注释和debugging语句,通常是我必须检查的代码量的三倍,以find我正在寻找的东西。

不使用“&”购买你的主要原因是它可以让你使用函数原型。 但是Perl函数的原型可能会像创build它们一样频繁地创build错误,因为它们会以您不希望的方式将您的参数列表重新解释,以便您的函数调用不再传递它所expression的参数。

Interesting Posts