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

时间:2010-03-20 22:44:25

标签: perl prototype subroutine

我一直在使用Perl,但今天我遇到了这段代码:

sub function1($$)
{
   //snip
}

这在Perl中意味着什么?

2 个答案:

答案 0 :(得分:16)

这是一个prototype的函数,它带有两个标量参数。


如下面的评论中所述,有一些强有力的论据认为实际上并未实际使用Perl原型。最强烈的论点可能是:

有关2008年StackOverflow的讨论:

MooseX::Method::Signatures模块中可能有替换。

答案 1 :(得分:11)

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

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

sub foo($)  { ... }
sub bar($$) { ... }

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

foo bar 1, 2

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

foo(bar(1,2))

另一个例子:

bar foo 2, 3

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

bar(foo(2),3)

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

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

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

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

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

use MooseX::Method::Signatures;

method foo(Bar $a, Bar $b) { # fooify the bars
    ....

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