在另一个堆栈溢出问题中, Leon Timmermans断言:
我建议您不要使用原型。它们有其用途,但不适用于大多数情况,并且绝对不在此情况下使用。
为什么这可能是正确的(或相反)?我几乎总是为我的Perl函数提供原型,而且我从未见过有人对使用它们发表过不好的看法。
在另一个堆栈溢出问题中, Leon Timmermans断言:
我建议您不要使用原型。它们有其用途,但不适用于大多数情况,并且绝对不在此情况下使用。
为什么这可能是正确的(或相反)?我几乎总是为我的Perl函数提供原型,而且我从未见过有人对使用它们发表过不好的看法。
Answers:
如果使用正确,原型也不错。困难在于Perl的原型无法像人们通常期望的那样工作。具有其他编程语言背景的人们倾向于期望原型提供一种机制来检查函数调用是否正确:也就是说,他们具有正确的数量和类型的参数。Perl的原型并不适合此任务。这是滥用这是很糟糕。Perl的原型有一个独特且截然不同的目的:
原型允许您定义行为类似于内置函数的函数。
例如,您可以定义如下函数:
sub mypush(\@@) { ... }
并称其为
mypush @array, 1, 2, 3;
无需编写\
即可获取对数组的引用。
简而言之,原型使您可以创建自己的语法糖。例如,Moose框架使用它们来模拟更典型的OO语法。
这非常有用,但是原型非常有限:
有关所有血腥细节,请参见perlsub中的原型。
问题在于Perl的函数原型无法实现人们认为的功能。它们的目的是允许您编写将像Perl的内置函数一样被解析的函数。
首先,方法调用完全忽略了原型。如果您正在执行OO编程,则方法具有的原型无关紧要。(因此,他们不应该有任何原型。)
其次,没有严格执行原型。如果您使用调用子例程&function(...)
,则原型将被忽略。因此,它们实际上并没有提供任何类型安全性。
第三,它们是遥不可及的诡异动作。(特别是$
原型,它导致在标量上下文而不是默认列表上下文中评估相应的参数。)
特别是,它们使从数组传递参数变得困难。例如:
my @array = qw(a b c);
foo(@array);
foo(@array[0..1]);
foo($array[0], $array[1], $array[2]);
sub foo ($;$$) { print "@_\n" }
foo(@array);
foo(@array[0..1]);
foo($array[0], $array[1], $array[2]);
印刷品:
a b c
a b
a b c
3
b
a b c
以及3条有关的警告main::foo() called too early to check prototype
(如果启用了警告)。问题在于,在标量上下文中求值的数组(或数组切片)将返回数组的长度。
如果您需要编写一个类似于内置函数的函数,请使用原型。否则,请勿使用原型。
注意:Perl 6将完全改写并且非常有用的原型。此答案仅适用于Perl 5。
foo()
打印件2,因为那是您的两个元素切片中的最后一个元素。更改为my @array = qw(foo bar baz)
,您将看到不同之处。(顺便说一句,这就是为什么我没有在一次性的说明性代码中将数组/列表初始化为基于0或1的数字序列的原因。上下文中索引,计数和元素之间的混淆不止一次使我痛苦。愚蠢但真实。)
a b c
以使您的观点更加清楚。
有些人看着Perl子例程原型,认为这意味着它不具有以下含义:
sub some_sub ($$) { ... }
对于Perl,这意味着解析器需要两个参数。这是Perl的一种方法,它使您可以创建行为类似于内置程序的子例程,所有这些子例程都知道对后续代码的期望。您可以在perlsub中阅读有关原型的信息
人们在不阅读文档的情况下猜测,原型是指运行时参数检查或其他语言中看到的类似内容。与大多数人对Perl的猜测一样,事实证明它们是错误的。
但是,从Perl v5.20开始,Perl具有一项功能,在我撰写本文时是实验性的,它提供了更多类似于用户期望和期望的功能。Perl的子例程签名可以进行运行时参数计数,变量分配和默认设置:
use v5.20;
use feature qw(signatures);
no warnings qw(experimental::signatures);
animals( 'Buster', 'Nikki', 'Godzilla' );
sub animals ($cat, $dog, $lizard = 'Default reptile') {
say "The cat is $cat";
say "The dog is $dog";
say "The lizard is $lizard";
}
如果您正在考虑使用原型,那么这可能就是您想要的功能。