函数声明"sub function($$)"是什么意思?

sud*_*03r 6 perl prototype subroutine

我已经使用Perl一段时间了,但今天我遇到了这段代码:

sub function1($$)
{
   //snip
}
Run Code Online (Sandbox Code Playgroud)

这在Perl中意味着什么?

Jon*_*ler 16

它是一个带有两个标量参数的原型函数.


对于实际上没有实际使用Perl原型有强有力的论据 - 如下面的评论中所述.最强烈的论点可能是:

从2008年开始讨论StackOverflow:

MooseX :: Method :: Signatures模块中可能存在替换.

  • 现代Perl中没有使用原型,因为它们已被破坏.怎么坏了?这是最近的一个问题,它只能说明其中的一个问题:http://stackoverflow.com/questions/2485106/why-do-printf-and-sprintf-behave-differently原型不用于类型检查,它们是提示编译器,Perl将*强制调用者的参数以适应原型*,即使它们是错误的. (3认同)
  • 有关原型的(更详细)警告,请阅读http://web.archive.org/web/20030704193247/http://perl.com/pub/a/language/misc/fmproto.html (2认同)
  • 不要在Perl中使用原型.这条规则很少有例外. (2认同)

jro*_*way 11

正如另一个答案所提到的那样,$$声明了一个原型.另一个答案没有说的是原型的用途.它们不用于输入验证,它们是解析器的提示.

想象一下,你有两个声明的函数:

sub foo($)  { ... }
sub bar($$) { ... }
Run Code Online (Sandbox Code Playgroud)

现在当你写一些含糊不清的东西时,比如:

foo bar 1, 2
Run Code Online (Sandbox Code Playgroud)

Perl知道在哪里放置parens; bar需要两个args,所以它会消耗最接近它的两个args.foo需要一个arg,所以它需要bar和两个args的结果:

foo(bar(1,2))
Run Code Online (Sandbox Code Playgroud)

另一个例子:

bar foo 2, 3
Run Code Online (Sandbox Code Playgroud)

同样适用; foo需要一个arg,所以得到2. bar需要两个args,所以得到foo(2)3个:

bar(foo(2),3)
Run Code Online (Sandbox Code Playgroud)

这是Perl非常重要的一部分,因此将其视为"永不使用"会对您造成伤害.几乎每个内部函数都使用原型,因此通过了解它们在您自己的代码中的工作方式,您可以更好地理解内部函数如何使用它们.然后你可以避免不必要的括号,这使得代码更加令人愉悦.

最后,一个反模式我将警告你反对:

package Class;
sub new ($$) { bless $_[1] }
sub method ($) { $_[0]->{whatever} }
Run Code Online (Sandbox Code Playgroud)

当您将代码作为方法(Class->method$instance->method)调用时,原型检查完全没有意义.如果您的代码只能作为方法调用,则添加原型是错误的.我见过一些流行的模块(hello,XML::Compile),但这是错的,所以不要这样做.如果你想记录要通过的args数量,那么:

sub foo {
    my ($self, $a, $b) = @_; # $a and $b are the bars to fooify
    ....
Run Code Online (Sandbox Code Playgroud)

要么

use MooseX::Method::Signatures;

method foo(Bar $a, Bar $b) { # fooify the bars
    ....
Run Code Online (Sandbox Code Playgroud)

不同foo($$),这些是有意义和可读的.