我听说人们不应该&用来调用Perl subs,即:
function($a,$b,...);
# opposed to
&function($a,$b,...);
Run Code Online (Sandbox Code Playgroud)
我知道一个参数列表变成可选的,但在某些情况下哪些是适合使用的,&以及你绝对不应该使用它的情况?
当省略时,性能增加如何发挥作用&呢?
bri*_*foy 52
我经常被滥用&,但主要是因为我做了很奇怪的界面.如果您不需要其中一种情况,请不要使用&.其中大多数只是访问子程序定义,而不是调用子程序.这一切都在perlsub中.
引用一个命名子例程.这可能是大多数Perlers的唯一常见情况:
my $sub = \&foo;
Run Code Online (Sandbox Code Playgroud)同样,分配给typeglob,它允许您使用不同的名称调用子例程:
*bar = \&foo;
Run Code Online (Sandbox Code Playgroud)检查是否定义了子例程,就像在测试套件中一样:
if( defined &foo ) { ... }
Run Code Online (Sandbox Code Playgroud)删除子例程定义,这不应该是常见的:
undef &foo;
Run Code Online (Sandbox Code Playgroud)提供一个调度程序子程序,其唯一的工作是选择要调用的正确子程序.这是我唯一使用的情况&来调用一个子程序,当我想到打电话给调度员无数次,需要挤一点表现出来的操作:
sub figure_it_out_for_me {
# all of these re-use the current @_
if( ...some condition... ) { &foo }
elsif( ...some other... ) { &bar }
else { &default }
}
Run Code Online (Sandbox Code Playgroud)跳进其他子程序使用当前参数堆栈(和更换在调用栈中的当前子程序),在分派unrare操作,特别是在AUTOLOAD:
goto ⊂
Run Code Online (Sandbox Code Playgroud)调用您在Perl内置后命名的子例程.将&始终为您提供了用户定义的.这就是我们在Learning Perl中教它的原因.你真的不想这样做,但它是其中一个特点&.
有些地方你可以使用它们,但有更好的方法:
调用与内置Perl同名的子例程.只是没有与内置Perl同名的子程序.检查perlfunc以查看不应使用的内置名称列表.
要禁用原型.如果您不知道这意味着什么或为什么需要它,请不要使用&.一些黑魔法代码可能需要它,但在这些情况下你可能知道你在做什么.
取消引用并执行子例程引用.只需使用->符号.
cha*_*aos 36
IMO,唯一有理由使用的&是你获得或调用coderef,如:
sub foo() {
print "hi\n";
}
my $x = \&foo;
&$x();
Run Code Online (Sandbox Code Playgroud)
主要的时间,你可以,你使用它绝对不应该在大多数情况下,调用一个已具雏形,指定任何非默认调用行为子时.我的意思是,一些原型允许重新解释参数列表,例如转换@array和%hash规范参考.因此,sub会期望这些重新解释已经发生,并且除非你达到手动模仿它们所需的任何长度,否则sub将获得与它预期的输入大不相同的输入.
我认为主要是人们试图告诉你,你仍然用Perl 4风格写作,现在我们有一个更干净,更好的东西叫做Perl 5.
关于性能,Perl有多种方法可以优化&失败的子调用,其中一个主要是内联常量.
还有一种情况是使用&提供了性能优势:如果您正在转发子呼叫foo(@_).使用&foo比无限快foo(@_).除非你通过剖析确定你需要微观优化,否则我不会推荐它.
cms*_*cms 18
&subroutine()表单禁用原型检查.这可能是也可能不是你想要的.
http://www.perl.com/doc/manual/html/pod/perlsub.html#Prototypes
原型允许您指定子例程参数的数量和类型,并在编译时检查它们.这可以提供有用的诊断帮助.
原型不适用于方法调用,也不适用于使用&前缀的旧式样式调用.
&必须引用或取消引用子例程或代码引用
例如
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
Run Code Online (Sandbox Code Playgroud)
原型也不适用于子程序引用.
&subroutine表单也用于所谓的magic goto表单.
该表达式goto &subroutine使用@_的当前值替换当前调用上下文,并调用named子例程.
实质上,您可以通过调用指定的子程序将调用完全切换到一个子例程.这在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
}
Run Code Online (Sandbox Code Playgroud)
}
我想这可能对尾部呼叫消除有用.