当前位置:  开发笔记 > 编程语言 > 正文

为什么Perl 5的功能原型很糟糕?

如何解决《为什么Perl5的功能原型很糟糕?》经验,为你挑选了3个好方法。

在另一个Stack Overflow问题中, Leon Timmermans断言:

我建议你不要使用原型.它们有它们的用途,但对大多数情况并非如此,绝对不是在这个例子中.

为什么这可能是真的(或其他)?我几乎总是为我的Perl函数提供原型,而且我从来没有见过其他任何人说使用它们的坏事.



1> Michael Carm..:

如果使用正确,原型也不错.困难在于Perl的原型不像人们通常期望的那样工作.具有其他编程语言背景的人倾向于期望原型提供检查函数调用是否正确的机制:即,他们具有正确数量和类型的参数.Perl的原型并不适合这项任务.这是滥用,这是不好的.Perl的原型有一个非常不同的目的:

原型允许您定义与内置函数类似的函数.

括号是可选的.

上下文强加于参数.

例如,您可以定义这样的函数:

sub mypush(\@@) { ... }

并称之为

mypush @array, 1, 2, 3;

无需编写\以获取对数组的引用.

简而言之,原型可以让你创建自己的语法糖.例如,Moose框架使用它们来模拟更典型的OO语法.

这非常有用,但原型非常有限:

它们必须在编译时可见.

他们可以被绕过.

将上下文传播到参数可能会导致意外行为.

它们使得使用除严格规定的表格之外的任何东西来调用函数变得困难.

有关所有血腥细节,请参阅perlsub中的Prototypes.


[远远超过你想知道的关于Perl原型的一切](http://www.perlmonks.org/?node_id=861966).
我已经接受了这个答案,因为我觉得它最能回答这个问题 - 原型并不是本质上不好的,它只是你如何使用它们.
另一方面,Moose原型是/ awesome/http://p3rl.org/MooseX::Declare http://p3rl.org/MooseX::Method :: Signign

2> cjm..:

问题是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.


更正:数组切片返回*list*,因此标量上下文中的数组切片返回列表的最后一个元素.你对`foo()`的倒数第二次调用打印2,因为这是你的两个元素切片中的最后一个元素.改为"我的@array = qw(foo bar baz)",你会看到差异.(顺便说一句,这就是为什么我不会在一次性的示范代码中将数组/列表初始化为基于0或1的数字序列.上下文中的索引,计数和元素之间的混淆不止一次地困扰我.傻但真实.)
有更好的方法来验证参数,例如Params :: Validate模块:http://search.cpan.org/~drolsky/Params-Validate-0.91/lib/Params/Validate.pm
没有; 普遍的共识是Perl函数原型基本上没有带来任何好处.你也可以不打扰他们,至少在Perl 5中.Perl 6可能是一个不同的(更好的)故事.
@pilcrow:我编辑了使用`abc`的答案,让你的观点更加清晰.

3> Leon Timmerm..:

我同意上述两张海报.通常,$应避免使用.原型中使用块参数(当只有有用&),水珠(*),或参考原型(\@,\$,\%,\*)

推荐阅读
php
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有