我在Windows 7上运行ActiveState的32位ActivePerl 5.14.2。我想用Git预提交钩子来检测有语法错误的检入程序。(不知怎么的,我就做了这么糟糕的承诺。)所以作为一个测试程序,我随机写下了这个:
use strict; use warnings; Syntax error! exit 0;
但是,它编译和执行时没有警告,退出时errorlevel为零。这是如何有效的语法?
我不知道为什么,但是Perl是这样做的:
perl -MO=Deparse -w yuck BEGIN { $^W = 1; } use warnings; use strict 'refs'; 'error'->Syntax(!exit(0)); yuck syntax OK
解析器似乎认为你在error-object上调用方法Syntax…奇怪的!
error
Syntax
Perl有一种称为“间接方法符号”的语法。它允许
Foo->new($bar)
写成
new Foo $bar
这意味着
Syntax error ! exit 0;
和
error->Syntax(! exit 0);
或
error->Syntax(!exit(0));
它不仅语法有效,而且不会导致运行时错误,因为首先执行的是exit(0)。
exit(0)
没有得到错误的原因是第一次执行的代码是错误的
exit(0);
因为第一行没有分号:
Syntax error!
编译器会(错误地)猜测这是一个带有not运算符!的子例程调用。然后它将执行该子例程的参数,该子例程恰好是exit(0),此时程序退出并将errorlevel设置为0。不执行任何其他操作,因此不再报告运行时错误。
not
!
你会注意到,如果你把exit(0)改成类似print "Hello world!"的东西,你会得到一个错误:
print "Hello world!"
Can't locate object method "Syntax" via package "error" ...
你的错误级别将被设置:
> echo %errorlevel% 255
如上所述,这是由间接方法调用符号引起的。你可以警告:
use strict; use warnings; no indirect; Syntax error! exit 0;
生产:
Indirect call of method "Syntax" on object "error" at - line 5.
这需要间接CPAN模块。
你也可以使用no indirect "fatal";来终止程序(这就是我所做的)
no indirect "fatal";
尝试Perl 6,它似乎更容易满足你的期望:
===SORRY!=== Error while compiling synerror.p6 Negation metaoperator not followed by valid infix at synerror.p6:1 ------> Syntax error!⏏<EOL> expecting any of: infix infix stopper
在这个纸中,我们的目标是回答一个长期存在的问题 编程语言社区:有没有可能涂上油漆 没有创建有效的Perl?< / p >
TLDR;几乎没有