我在 Windows 7 上运行 ActiveState 的 32 位ActivePerl 5.14.2。我想弄乱一个 Git 预提交挂钩来检测正在签入的程序是否存在语法错误。(不知何故,我只是设法做了这么糟糕的提交。)所以作为一个测试程序,我随机记下这个:
use strict;
use warnings;
Syntax error!
exit 0;
但是,它编译并执行时没有警告,并且错误级别在退出时为零。这个有效的语法如何?
我在 Windows 7 上运行 ActiveState 的 32 位ActivePerl 5.14.2。我想弄乱一个 Git 预提交挂钩来检测正在签入的程序是否存在语法错误。(不知何故,我只是设法做了这么糟糕的提交。)所以作为一个测试程序,我随机记下这个:
use strict;
use warnings;
Syntax error!
exit 0;
但是,它编译并执行时没有警告,并且错误级别在退出时为零。这个有效的语法如何?
Perl 有一种称为“间接方法表示法”的语法。它允许
Foo->new($bar)
写成
new Foo $bar
所以这意味着
Syntax error ! exit 0;
是相同的
error->Syntax(! exit 0);
或者
error->Syntax(!exit(0));
它不仅是有效的语法,而且不会导致运行时错误,因为首先执行的是exit(0)
.
我不知道为什么,但这就是 Perl 所做的:
perl -MO=Deparse -w yuck
BEGIN { $^W = 1; }
use warnings;
use strict 'refs';
'error'->Syntax(!exit(0));
yuck syntax OK
似乎解析器认为您正在调用-objectSyntax
上的方法error
......确实很奇怪!
您没有收到错误的原因是第一个执行的代码是
exit(0);
因为第一行没有分号:
Syntax error!
编译器将(错误地)猜测这是一个带有not
运算符的子例程调用!
。然后它将执行该子例程的参数,该子例程恰好是exit(0)
,此时程序退出并将 errorlevel 设置为 0。不执行其他任何操作,因此不再报告运行时错误。
您会注意到,如果您更改exit(0)
为类似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";
用来导致程序死掉(这就是我所做的)
试试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 的情况下将油漆涂抹在墙上?
TLDR;几乎不