这是Perl的glob原型的错误吗?

时间:2011-04-08 19:02:32

标签: perl syntax prototype

由于没有特别的原因,我正在使用glob原型(*),并查看当参数是已定义的子例程时它会做什么。

给出以下代码:

sub test (*) {print "[@_]\n"}
sub blah ($) {"blah got @_"}

如果您写test blah;,则会收到语法错误Not enough arguments for main::blah...

如果你写test blah 1;,程序会编译并打印[blah]

如果你编写test blah die;程序编译,打印[blah]并且不会死。

如果你写test blah(1);,程序会编译并打印[blah got 1]

如果你写test blah(die);,程序会编译然后死掉。

最后两个例子显然是“如果它看起来像子程序调用它是一个子程序调用”规则的应用。

然而,没有括号的例子对我来说似乎是个错误。因为似乎正在发生的事情是,尽管在glob上下文中,解析器仍然将blah视为需要参数的原型函数。但是,当说完并完成编译时,blah的参数将被完全抛弃,字符串'blah'将传递给test

以下是贯穿test blah die;的{​​{1}}构造的示例:

B::Deparse

正如您所看到的,$ perl -MO=Deparse,-p -e 'sub test (*) {print "[@_]\n"} sub blah ($) {"blah got @_"} test blah die;' sub test (*) { print("[@_]\n"); } sub blah ($) { "blah got @_"; } &test('blah'); -e syntax OK 完全从操作树中删除。

所以我的问题是,如果其他人认为这种行为是一个错误?行为记录在任何地方吗?如果它是一个bug,是否值得修复?

2 个答案:

答案 0 :(得分:3)

Perl中的原型是bad news。他们非常破碎。实际上,它们完美地工作,但是我们凡人的大脑无法想象Perl原型的全部深度。

他们假设允许您调用用户定义的函数,就好像它是一个内置函数,但它们如何工作是非常混乱的。请参阅Perldoc persub了解它们的工作原理(并且不起作用)。

从Perl函数调用中移除括号已经有一段时间了,我猜在某些情况下,删除无关的括号可以使代码更容易阅读。然而,这个微小的改进并不足以克服原型设计的陷阱。

你肯定在寻找原型设计的极限。实际上,您的代码实际上非常混乱,添加括号会提高其可读性。是的,我知道这不是你的目的。你的目的是考虑Perl原型设计,直到你成为Larry Wall的一员。我很感激你的勇气。我尝试了原型设计,直到我哭着走进卧室,砰地关上门,拒绝出门直到晚餐。经过多年的心理治疗和大量饮酒,克服了我使用Perl原型制作的经验。即使在今天,每当我看到\@@时,我都会无法控制地哭泣。

Perl 6假设让一切都变得更好。不幸的是,Perl 6的工作时间比 Duke Nukem Forever 长。

轻微夸张。 Duke Nukem实际上是在1997年宣布的,而Perl 6是在2000年宣布的,所以Duke Nukem实际上在Perl 6上已经有三年了。但是,Duke Nukem实际上有一个发布日期(2011年6月),这更像是Perl 6具有

好的,足够的抓地力。你可能最好在Perlmonks网站上寻求帮助。这就是Perl大师们的出路。他们可以解释你的程序正在发生的一切,以及为什么它正在做正确的事情。

  

David Weintraub

     

perl -e'print“只是另一个第二速率Perl hacker \ n”;'


附录

似乎远远超过你曾经想知道的关于Perl中原型的所有内容已被移至Perl Monks。这篇文章将解释为什么你的原型按预期行为

答案 1 :(得分:0)

这感觉就像一个错误,但你期待发生什么?

玩过更多的Perl似乎确实在使用某种扭曲的情报。

test blah 1 2 

失败,因为2被认为是不相关的。

所以'blah 1'传递一个带有1个参数的函数的检查,但是然后glob处理不会选择它。使用标量原型可以满足您的期望。

sub test (*) {print "[@_]\n"} 

==> blah got 1

我还检查了是否有更多参数......

sub test(*) { print "[$_[0] $_[1]]\n" }

$ _ [1]的炸弹不存在。