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

Bil*_*ert 487 perl

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

use strict;
use warnings;

Syntax error!

exit 0;
Run Code Online (Sandbox Code Playgroud)

但是,它在没有警告的情况下编译和执行,退出时errorlevel为零.这个有效的语法怎么样?

ike*_*ami 536

Perl有一种称为"间接方法表示法"的语法.它允许

Foo->new($bar)
Run Code Online (Sandbox Code Playgroud)

写成

new Foo $bar
Run Code Online (Sandbox Code Playgroud)

这意味着

Syntax error ! exit 0;
Run Code Online (Sandbox Code Playgroud)

是相同的

error->Syntax(! exit 0);
Run Code Online (Sandbox Code Playgroud)

要么

error->Syntax(!exit(0));
Run Code Online (Sandbox Code Playgroud)

它不仅是有效的语法,它不会导致运行时错误,因为执行的第一件事是exit(0).

  • @Hassan,语言有类型.具体而言,值具有类型.运算符和子函数不仅限于返回特定类型的值.事实证明这是非常有用的,只需很少的费用(由于警告). (11认同)
  • @Hassan,想一想,`!exit(0)`不能再是`!$ x`的类型错误,因为它们都没有输入. (6认同)
  • @Nawaz,它实际上很受欢迎.每个人都使用它来构建Java和C++中的对象,以及大量的Perl程序员使用`new Class`和`print $ fh ...`而不是`Class-> new(...)`和`$ FH->打印(...)`.不过,我会告诉你它会导致一个奇怪的错误信息 (6认同)
  • 我把它读作"语法错误!退出0;",但我没有考虑间接调用.花了很多时间忘记了! (2认同)

pav*_*vel 109

我不知道为什么,但这就是Perl所做的:

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

似乎解析器认为你在-object Syntax上调用方法error......确实是奇怪的!

  • 恭喜.您找到了一个程序,您需要在其中添加分号以使编译失败. (117认同)
  • Perl似乎假设"间接(对象)语法",通常像`new Class`而不是`Class-> new()`一样使用.要调用方法`Syntax`,执行`exit`函数,因此运行时错误永远不会发生. (6认同)
  • 这是间接方法调用语法.这是(有点)在这里工作,因为首先计算`exit(0)`,使程序在尝试将结果传递给''error' - > Syntax()之前退出. (3认同)

TLP*_*TLP 53

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

exit(0);
Run Code Online (Sandbox Code Playgroud)

因为第一行没有分号:

Syntax error!
Run Code Online (Sandbox Code Playgroud)

编译器会猜测(错误地)这是一个带有not操作符的子程序调用!.然后它将执行该子程序的参数,恰好是exit(0)程序退出并将errorlevel设置为0.其他任何执行都没有执行,因此不再报告运行时错误.

您会注意到,如果您更改exit(0)为类似的内容,print "Hello world!"则会收到错误消息:

Can't locate object method "Syntax" via package "error" ...
Run Code Online (Sandbox Code Playgroud)

并将设置您的错误级别:

> echo %errorlevel%
255
Run Code Online (Sandbox Code Playgroud)

  • @LiamLaverty是的,它可以.它可以错误地猜出人类意味着什么. (14认同)
  • `>编译器会猜测(错误地)`编译器不能正确地做任何事情. (7认同)
  • 等式中的人是不正确的.编译器只能"正确"或"损坏".它没有对语言的定义或用户的意图得出意见. (4认同)
  • @LiamLaverty如果能在这种情况下猜测用户的意图,那将是一个非常简洁的编译器,是的.因此,编译器无法正确猜测.您可能正在对我的语句进行一些技术术语分析,​​我可能会补充说,这是不正确的阅读方式. (4认同)

Mar*_*ler 33

如上所述,这是由间接方法调用符号引起的.你可以警告:

use strict;
use warnings;
no indirect;

Syntax error!

exit 0;
Run Code Online (Sandbox Code Playgroud)

生产:

Indirect call of method "Syntax" on object "error" at - line 5.
Run Code Online (Sandbox Code Playgroud)

这需要间接CPAN模块.

你也可以no indirect "fatal";用来导致程序死掉(这就是我所做的)


mor*_*itz 8

尝试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
Run Code Online (Sandbox Code Playgroud)