我应在何时使用&;调用Perl子例程?

我应在何时使用&;调用Perl子例程?,perl,subroutine,Perl,Subroutine,我听说人们不应该使用&来调用Perl subs,即: function($a,$b,...); # opposed to &function($a,$b,...); 我知道参数列表是可选的,但是在哪些情况下使用&是合适的,哪些情况下绝对不应该使用它 此外,当省略&时,性能增加是如何发挥作用的?在我看来,唯一有理由使用&的时间是在您获取或调用coderef时,例如: sub foo() { print "hi\n"; } my $x = \&foo; &$x()

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

function($a,$b,...);
# opposed to
&function($a,$b,...);
我知道参数列表是可选的,但是在哪些情况下使用
&
是合适的,哪些情况下绝对不应该使用它


此外,当省略
&
时,性能增加是如何发挥作用的?

在我看来,唯一有理由使用
&
的时间是在您获取或调用coderef时,例如:

sub foo() {
    print "hi\n";
}

my $x = \&foo;
&$x();
在大多数情况下,您可以使用它(绝对不应该)的主要时间是在调用具有指定任何非默认调用行为的原型的sub时。我的意思是,一些原型允许重新解释参数列表,例如将
@array
%hash
规范转换为引用。因此,sub将期望这些重新解释已经发生,除非你用手去模仿它们,否则sub将得到与预期完全不同的输入

我想人们主要是想告诉你,你仍然在用Perl4风格写作,现在我们有了一个更干净、更好的东西,叫做Perl5

关于性能,Perl优化子调用的方法有多种,
&
会失败,其中一种主要方法是常量内联

还有一种情况下,使用
&
可以提高性能:如果您使用
foo(@41;
转发子呼叫。使用
&foo
foo(@)
快无穷多。我不推荐它,除非您通过分析最终发现您需要这种微优化。

subroutine()表单禁用原型检查。这可能不是你想要的

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

原型不适用于方法调用,也不适用于使用&prefix的老式样式的调用

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

e、 g

Protypes也不适用于子例程引用

&subroutine形式也用于所谓的形式

表达式
goto&subroutine
将当前调用上下文替换为使用@的当前值调用指定的子例程

本质上,您可以通过调用指定的子例程来完全切换对一个子例程的调用。这在自动加载块中很常见,在自动加载块中可以进行延迟子例程调用,可能需要对@进行一些修改,但在程序看来,它完全像是对指定子例程的调用

e、 g

}

我想,这可能会对你有用


请看

我经常滥用
&
,但主要是因为我在做一些奇怪的界面工作。如果您不需要这些情况之一,请不要使用
&
。其中大多数只是访问子例程定义,而不是调用子例程。都在里面

  • 引用指定的子例程。这可能是大多数人的唯一常见情况:

     my $sub = \&foo;
    
  • 类似地,分配给typeglob,这允许您使用不同的名称调用子例程:

     *bar = \&foo;
    
  • 检查是否定义了子例程,如您在测试套件中所做的:

     if( defined &foo ) { ... }
    
  • 删除子例程定义,该定义不应该是公共的:

     undef &foo;
    
  • 提供一个调度程序子例程,其唯一任务是选择要调用的正确子例程。这是我使用
    &
    调用子例程的唯一情况,当我希望多次调用调度程序并需要从操作中挤出一点性能时:

     sub figure_it_out_for_me {
        # all of these re-use the current @_
          if( ...some condition... ) { &foo     } 
       elsif( ...some other...     ) { &bar     }
       else                          { &default }
       }
    
  • 要使用当前参数堆栈跳转到另一个子例程(并替换调用堆栈中的当前子例程),分派中的UNRRE操作,尤其是在
    自动加载中:

     goto ⊂
    
  • 调用以Perl内置代码命名的子例程。
    &
    始终提供用户定义的代码。那是。您并不想正常地这样做,但这是
    &
    的功能之一

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

  • 调用与Perl内置程序同名的子例程。只是没有与Perl内置程序同名的子例程。查看不应使用的内置名称列表

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

  • 取消引用并执行子例程引用。只需使用
    ->
    符号即可


  • 我读过反对使用“&”的论点,但我几乎总是使用它。这节省了我太多的时间。我花了大量Perl编码时间寻找代码中调用特定函数的部分。使用前导&,我可以立即搜索并找到它们。如果没有前导&,我会得到函数定义、注释和调试语句,通常需要检查三倍的代码才能找到所需的内容


    不使用“&”的主要原因是它允许您使用函数原型。但是Perl函数原型可能会创建错误,因为它们会以您可能不期望的方式重新解释您的参数列表,从而使您的函数调用不再传递它字面上所说的参数。

    您能详细介绍一下“非默认调用行为”部分吗?除了,
    和$x之外()
    并不是调用代码引用的最佳方式;您可能应该像其他任何引用一样取消引用它:$x->()
     sub figure_it_out_for_me {
        # all of these re-use the current @_
          if( ...some condition... ) { &foo     } 
       elsif( ...some other...     ) { &bar     }
       else                          { &default }
       }
    
     goto ⊂