我一直在使用Perl,但今天我遇到了这段代码:
sub function1($$)
{
//snip
}
这在Perl中意味着什么?
答案 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($$)
不同,这些是有意义且可读的。