Aln*_*tak 116 perl prototype function
在另一个Stack Overflow问题中, Leon Timmermans断言:
我建议你不要使用原型.它们有它们的用途,但对大多数情况并非如此,绝对不是在这个例子中.
为什么这可能是真的(或其他)?我几乎总是为我的Perl函数提供原型,而且我从来没有见过其他任何人说使用它们的坏事.
Mic*_*man 121
如果使用正确,原型也不错.困难在于Perl的原型不像人们通常期望的那样工作.具有其他编程语言背景的人倾向于期望原型提供检查函数调用是否正确的机制:即,他们具有正确数量和类型的参数.Perl的原型并不适合这项任务.这是滥用,这是不好的.Perl的原型有一个非常不同的目的:
原型允许您定义与内置函数类似的函数.
例如,您可以定义这样的函数:
sub mypush(\@@) { ... }
Run Code Online (Sandbox Code Playgroud)
并称之为
mypush @array, 1, 2, 3;
Run Code Online (Sandbox Code Playgroud)
无需编写\
以获取对数组的引用.
简而言之,原型可以让你创建自己的语法糖.例如,Moose框架使用它们来模拟更典型的OO语法.
这非常有用,但原型非常有限:
有关所有血腥细节,请参阅perlsub中的Prototypes.
cjm*_*cjm 69
问题是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]);
Run Code Online (Sandbox Code Playgroud)
打印:
a b c
a b
a b c
3
b
a b c
Run Code Online (Sandbox Code Playgroud)
以及3个警告main::foo() called too early to check prototype
(如果启用了警告).问题是在标量上下文中计算的数组(或数组切片)返回数组的长度.
如果您需要编写一个类似于内置函数的函数,请使用原型.否则,不要使用原型.
注意:Perl 6将完全改造并且非常有用的原型.这个答案仅适用于Perl 5.
Leo*_*ans 30
我同意上述两张海报.通常,$
应避免使用.原型中使用块参数(当只有有用&
),水珠(*
),或参考原型(\@
,\$
,\%
,\*
)
有些人在查看 Perl 子程序原型时,认为这意味着它不具有的含义:
sub some_sub ($$) { ... }
Run Code Online (Sandbox Code Playgroud)
对于 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";
}
Run Code Online (Sandbox Code Playgroud)
如果您正在考虑原型,这就是您可能想要的功能。