Bu program neden geçerli? Bir sözdizimi hatası oluşturmaya çalışıyordum


489

Windows 7'de ActiveState'in 32 bit ActivePerl 5.14.2'sini çalıştırıyorum . Sözdizimi hatalarıyla teslim edilen programları tespit etmek için Git ön işleme kancasıyla uğraşmak istedim. (Bir şekilde böyle kötü bir taahhütte bulunmayı başardım.) Yani bir test programı olarak bunu rastgele not aldım:

use strict;
use warnings;

Syntax error!

exit 0;

Ancak, hiçbir uyarı olmadan derler ve yürütür ve çıkışta hata seviyesi sıfırdır. Bu geçerli sözdizimi nasıl?


121
Sadece perl içine rastgele kelimeler yazmanın çalışma programları ürettiğini kanıtladınız mı?!?!?!?!
Peter M

10
@PeterM Çok rasgele kelimeler. Perl sözdizimi hakkında yeterince bilgim olmadığını kanıtladım. Şimdi biraz daha biliyorum.
Bill Ruppert

10
Muhtemelen no indirectbu olanların olmasını durdurmak istersiniz
LeoNerd

@LeoNerd Tavsiye için teşekkürler!
Bill Ruppert

1
Bu şimdiye kadarki en ünlü perl sorusu. Schwartz'ın pasajı olarak daha da iyi :whatever / 25 ; # / ; die "this dies!";
jm666

Yanıtlar:


540

Perl, "dolaylı yöntem gösterimi" adlı bir sözdizimine sahiptir. İzin veriyor

Foo->new($bar)

olarak yazılacak

new Foo $bar

Yani bu

Syntax error ! exit 0;

aynıdır

error->Syntax(! exit 0);

veya

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

Yalnızca geçerli bir sözdizimi değil, aynı zamanda yürütülen ilk şey olduğu için çalışma zamanı hatasına neden olmaz exit(0).


1
@Hassan, Neden? Ardından bir ifade gelir.
ikegami

3
"Sözdizimi hatası! Çıkış 0;" olarak okudum, ama dolaylı çağırma hakkında düşünmedim. Bunu unutmak için çok zaman geçirdim!
Bill Ruppert

6
@Hassan, Bu şekilde düşünün, ikisi de yazıldığından !exit(0)daha fazla bir tür hata olamaz !$x.
ikegami

11
@Hassan, Dilin türleri var. Özellikle, değerlerin türleri vardır. İşleçler ve alt öğeler, belirli değer türlerini döndürmekle sınırlı değildir. Bu, çok az maliyetle çok yararlı olduğu ortaya çıkıyor (uyarılar sayesinde).
ikegami

6
@Nawaz, Aslında oldukça popüler. Java ve C ++ 'da nesneler oluşturan herkes new Classve ve print $fh ...yerine Class->new(...)ve kullanan büyük bir Perl programcıları tarafından kullanılır $fh->print(...). Yine de garip bir hata
mesajına

112

Nedenini bilmiyorum, ama Perl bunu yapıyor:

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

Ayrıştırıcı Syntax, error-object üzerinde yöntemi çağırdığınızı düşünüyor ... Gerçekten garip!


3
Bu dolaylı yöntem çağrı sözdizimi. Burada (bir çeşit) çalışıyor, çünkü önce exit(0)değerlendiriliyor ve sonucu geçmeye çalışmadan önce programdan çıkılıyor 'error'->Syntax().
duskwuff -inactive-

6
Perl genellikle new Classyerine kullanılan "dolaylı (nesne) sözdizimi" varsayıyor gibi görünüyor Class->new(). Yöntemini çağırmak için Syntax, exitfonksiyon yürütülür, bu nedenle çalışma zamanı hatası occures olmadı.
amon

118
Tebrikler. Derlemenin başarısız olması için noktalı virgül eklemeniz gereken bir program buldunuz.
mafya

use strict; use warnings; error->Syntax(! print "hi"); Verimler: Sözdizimi OK perl -MO = Deparse de, ama use warningsonunla yüklü olmadığını anlayabileceği için muhtemelen bir şey söylemelidir. Bunun yerine "Nesne yöntemi bulunamıyor .." bir çalışma zamanı hatası atar.

53

Hata almamanızın nedeni, ilk yürütülen kodun

exit(0);

İlk satırda noktalı virgül olmadığından:

Syntax error!

Derleyici, bunun atılmış bir notişleç içeren bir alt program çağrısı olduğunu (yanlış) tahmin edecektir !. Daha sonra, bu alt programın argümanlarını yürütecek exit(0)ve programın bu noktada çıkış seviyesi 0 olarak ayarlanmasına neden olacaktır. , böylece başka çalışma zamanı hataları bildirilmez.

Sizin exit(0)gibi bir şeye print "Hello world!"geçerseniz bir hata alırsınız:

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

ve hata seviyeniz ayarlanacaktır:

> echo %errorlevel%
255

7
>The compiler will guess (incorrectly) Derleyici yanlış bir şey yapamaz.
Liam Laverty

14
@LiamLaverty Evet, yapabilir. İnsanın ne anlama geldiğini yanlış tahmin edebilir.
TLP

4
Denklemde yanlış olan insandır. Derleyici yalnızca "doğru" veya "bozuk" olabilir. Dilin tanımı veya kullanıcının niyeti hakkında bir fikir sahibi değildir.
Liam Laverty

4
@LiamLaverty Kullanıcının bu durumda niyetini tahmin edebilirse oldukça düzgün bir derleyici olurdu, evet. Bu nedenle, derleyici doğru tahmin edemez. İfademin bazı teknik jargon analizlerini yapıyor olabilirsiniz, yani, yanlış okuma yolunu ekleyebilirim.
TLP

Bir yorumcu değil mi? ;-)
Rikki

33

Yukarıda belirtildiği gibi, buna dolaylı yöntem notasyon çağrısı neden olur. Bu konuda uyarabilirsiniz:

use strict;
use warnings;
no indirect;

Syntax error!

exit 0;

üretir:

Indirect call of method "Syntax" on object "error" at - line 5.

Bu dolaylı CPAN modülünü gerektirir .

no indirect "fatal";Programın ölmesine neden olmak için de kullanabilirsiniz (yaptığım budur)


8

Perl 6'yı deneyin , beklentilerinizi daha kolay yerine getiriyor gibi görünüyor:

===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

Bu yazıda , programlama dilleri topluluğunda uzun süredir devam eden açık bir soruna cevap vermeyi amaçlıyoruz: geçerli Perl oluşturmadan duvara boya bulaşmak mümkün mü?

TLDR; Zorlukla


Bunu sevdim. Bazı resimlerde taramak zorunda kalabilirim.
Bill Ruppert
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.