이 프로그램이 왜 유효합니까? 구문 오류를 만들려고했습니다.


489

Windows 7 에서 ActiveState의 32 비트 ActivePerl 5.14.2를 실행 하고 있습니다. 구문 오류로 체크인되는 프로그램을 감지하기 위해 Git 사전 커밋 후크를 사용하고 싶었습니다. (어쨌든 나는 방금 그런 나쁜 커밋을 할 수 있었다.) 그래서 테스트 프로그램으로 나는 이것을 무작위로 요했다.

use strict;
use warnings;

Syntax error!

exit 0;

그러나 경고없이 컴파일 및 실행되며 종료시 errorlevel은 0입니다. 이 유효한 구문은 어떻습니까?


121
펄에 임의의 단어를 입력하면 작동하는 프로그램이 생성된다는 것을 증명 했습니까 ??!?!?!?!
피터 M

10
@PeterM 거의 임의의 단어. 나는 Perl 구문에 대해 충분히 모른다는 것을 증명했다. 이제 조금 더 알고 있습니다.
Bill Ruppert

10
당신은 아마 no indirect그 것들의 발생을 막고 싶을 것입니다
LeoNerd

@LeoNerd 팁 주셔서 감사합니다!
Bill Ruppert

1
이것은 가장 유명한 펄 질문입니다. Schwartz의 발췌 문장 으로 더 나은 :whatever / 25 ; # / ; die "this dies!";
jm666

답변:


540

Perl에는 "간접 메소드 표기법"이라는 구문이 있습니다. 그것은 허용

Foo->new($bar)

로 작성

new Foo $bar

그러니까

Syntax error ! exit 0;

와 같다

error->Syntax(! exit 0);

또는

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

유효한 구문 일뿐만 아니라 실행 된 첫 번째 항목이이므로 런타임 오류가 발생하지 않습니다 exit(0).


1
@Hassan, 왜? 그 뒤에 표현식이옵니다.
ikegami

3
"Syntax error! exit 0;"로 읽는 것까지 간접 호출에 대해서는 생각하지 않았습니다. 그것을 잊고 많은 시간을 보냈습니다!
Bill Ruppert

6
@Hassan, 이런 식으로 생각하면 둘 다 입력하지 않았기 때문에 !exit(0)유형 오류가 될 수 없습니다 !$x.
ikegami

11
@Hassan, 언어 유형이 있습니다. 특히 값에는 유형이 있습니다. 연산자와 하위는 단순히 특정 유형의 값을 반환하는 데 국한되지 않습니다. 이것은 적은 비용으로 (경고 덕분에) 매우 유용한 것으로 판명되었습니다 .
ikegami

6
@ 나와 즈, 그것은 실제로 꽤 인기가 있습니다. 그것은 모두 그 구조의 자바와 C ++의 객체 및 그 용도 펄 프로그래머의 많은 기관에 의해 사용되는 new Classprint $fh ...대신 Class->new(...)하고 $fh->print(...). 나는 이상한 오류 메시지가 발생합니다, 당신을 부여하지만 것
이케 가미

112

이유를 모르겠지만 이것이 Perl이 만든 것입니다.

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

파서는 당신이 객체 에서 메소드 Syntax를 호출한다고 생각하는 것 같습니다 error... 정말로 이상합니다!


3
간접적 인 메소드 호출 구문입니다. exit(0)는 먼저 평가되어 결과를에 전달하려고 시도하기 전에 프로그램을 종료하기 때문에 여기에서 작동 합니다 'error'->Syntax().
duskwuff -inactive-

6
펄은 보통처럼 사용하는 "간접 (개체) 구문", 가정하는 것 new Class대신을 Class->new(). 메소드를 호출하기 Syntax위해 exit함수가 실행되므로 런타임 오류가 발생하지 않습니다.
amon

118
축하합니다. 컴파일이 실패하도록 세미콜론을 추가해야하는 프로그램을 찾았습니다.
mob

use strict; use warnings; error->Syntax(! print "hi"); 수율 : 구문 Ok on perl -MO = Deparse도 있지만 use warnings로드되지 않았 음을 알 수 있기 때문에 아마도 무언가를 말해야합니다. 대신 런타임 오류 "개체 메서드를 찾을 수 없습니다."가 발생합니다.

53

오류가 발생하지 않는 이유는 첫 번째로 실행 된 코드가

exit(0);

첫 번째 줄에 세미콜론이 없기 때문에 :

Syntax error!

컴파일러는 ( 이것은 not오퍼레이터가 !던져진 서브 루틴 호출이라고 추측합니다 .) 그런 다음이 서브 루틴에 대한 인수를 exit(0)실행합니다. 더 이상 런타임 오류가보고되지 않습니다.

exit(0)다음과 같이 변경 print "Hello world!"하면 오류가 발생합니다.

Can't locate object method "Syntax" via package "error" ...

오류 수준이 설정됩니다.

> echo %errorlevel%
255

7
>The compiler will guess (incorrectly) 컴파일러가 잘못 수행 할 수 없습니다.
Liam Laverty

14
@LiamLaverty 그렇습니다. 인간이 무엇을 의미했는지 잘못 추측 할 수 있습니다.
TLP

4
인간은 방정식에서 잘못된 것입니다. 컴파일러는 "올바른"또는 "손상된"만 될 수 있습니다. 언어의 정의 나 사용자의 의도에 대한 의견을 얻지 못합니다.
Liam Laverty

4
@LiamLaverty이 경우 사용자의 의도를 추측 할 수 있다면 꽤 깔끔한 컴파일러가 될 것입니다. 따라서 컴파일러가 올바르게 추측 할 수 없습니다. 내 진술에 대한 기술적 전문 용어 분석을 수행하고있을 수 있습니다. 즉, 문장을 읽는 잘못된 방법을 추가 할 수 있습니다.
TLP

통역이 아니십니까? ;-)
Rikki

33

위에서 언급했듯이 이것은 간접 메소드 호출 표기법으로 인해 발생합니다. 당신은 이것에 대해 경고 할 수 있습니다 :

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";프로그램을 죽이는 데 사용할 수도 있습니다 (이것이 내가하는 일입니다)


8

시도 펄 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

1

백서 에서는 프로그래밍 언어 커뮤니티에서 오랫동안 열려있는 문제에 답하고자합니다. 유효한 Perl을 만들지 않고 벽에 페인트를 칠할 수 있습니까?

TLDR; 거의


나는 그것을 좋아한다. 일부 사진을 스캔해야 할 수도 있습니다.
Bill Ruppert
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.