为什么这个计划有效?我试图创建一个语法错误

问题描述 投票:0回答:6

我正在 Windows 7 上运行 ActiveState 的 32 位 ActivePerl 5.14.2。我想使用 Git 预提交挂钩来检测正在签入的程序是否存在语法错误。 (不知怎的,我只是设法做了这么糟糕的提交。)所以作为一个测试程序,我随机记下了这个:

use strict;
use warnings;

Syntax error!

exit 0;

但是,它编译并执行时没有任何警告,并且退出时错误级别为零。这个语法如何有效?

perl
6个回答
573
投票

Perl 有一种称为“间接方法表示法”的语法。它允许

Foo->new($bar)

可写为

new Foo $bar

这意味着

Syntax error ! exit 0;

相同
error->Syntax(! exit 0);

error->Syntax(!exit(0));

它不仅是有效的语法,而且不会导致运行时错误,因为首先执行的是

exit(0)


可以使用以下任一方法禁用此“功能”:

no feature qw( indirect );  # Perl 5.32+

use v5.36;                  # Perl 5.36+

或者,您可以使用以下方式获取警告:

no indirect;                # CPAN module

118
投票

我不知道为什么,但这就是 Perl 的用途:

perl -MO=Deparse -w yuck
BEGIN { $^W = 1; }
use warnings;
use strict 'refs';
'error'->Syntax(!exit(0));
yuck syntax OK

解析器似乎认为您正在调用

Syntax
对象上的方法
error
...确实很奇怪!


57
投票

您没有收到错误的原因是第一个执行的代码是

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

35
投票

如上所述,这是由间接方法调用表示法引起的。您可以对此发出警告:

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";
来导致程序死掉(这就是我所做的)


6
投票

尝试一下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

3
投票

在这篇论文中,我们的目标是回答一个长期存在的开放性问题 编程语言社区:是否可以在上面涂抹油漆 墙没有创建有效的 Perl?

TLDR;几乎没有

© www.soinside.com 2019 - 2024. All rights reserved.