由于没有特别的原因,我正在使用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,是否值得修复?
答案 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]的炸弹不存在。