यह कार्यक्रम क्यों मान्य है? मैं एक वाक्य रचना त्रुटि बनाने की कोशिश कर रहा था


489

मैं विंडोज 7 पर ActiveState के 32 बिट ActivePerl 5.14.2 चला रहा हूं । मैं सिंटैक्स त्रुटियों के साथ चेक किए जा रहे कार्यक्रमों का पता लगाने के लिए Git प्री-कमिट हुक के साथ गड़बड़ करना चाहता था। (किसी तरह मैं सिर्फ इतना बुरा करने में कामयाब रहा।) इसलिए एक परीक्षण कार्यक्रम के रूप में मैंने इसे बेतरतीब ढंग से लिखा है:

use strict;
use warnings;

Syntax error!

exit 0;

हालाँकि, यह संकलित करता है और बिना किसी चेतावनी के चलता है, और बाहर निकलने पर एररवेलेवर शून्य है। यह वैध सिंटैक्स कैसे है?


121
क्या आपने अभी साबित किया है कि पर्ल में यादृच्छिक शब्द टाइप करने से काम के कार्यक्रम बनते हैं ??!?!?!?
पीटर एम

10
@PeterM शायद ही यादृच्छिक शब्द। मैंने साबित किया कि मुझे पर्ल सिंटैक्स के बारे में पर्याप्त जानकारी नहीं है। अब मुझे कुछ और पता है।
बिल रुपेर्ट

10
आप शायद no indirectउन लोगों को होने से रोकना चाहते हैं
लियोनेर्ड

@LeoNerd टिप के लिए धन्यवाद!
बिल रुपेर्ट

1
यह अब तक का सबसे प्रसिद्ध पर्ल प्रश्न है। श्वार्ट्ज स्निपेट के रूप में भी बेहतर है :whatever / 25 ; # / ; die "this dies!";
jm666

जवाबों:


540

पर्ल में एक सिंटैक्स है जिसे "इनडायरेक्ट मेथड नोटेशन" कहा जाता है। यह अनुमति देता है

Foo->new($bar)

के रूप में लिखा जाए

new Foo $bar

तो इसका मतलब

Syntax error ! exit 0;

के समान है

error->Syntax(! exit 0);

या

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

न केवल यह मान्य सिंटैक्स है, यह रन-टाइम त्रुटि में परिणाम नहीं करता है क्योंकि पहले निष्पादित की गई चीज है exit(0)


1
@ हसन, क्यों? यह एक अभिव्यक्ति के बाद है।
इकेगामी

3
मैं इसे "सिंटैक्स त्रुटि" के रूप में पढ़ने के रूप में दूर हो गया! 0 से बाहर निकलें; ", लेकिन मैं अप्रत्यक्ष आह्वान के बारे में नहीं सोचता था। भूल गए कि बहुत समय बिताया है!
बिल रुपेर्ट

6
@ हसन, इस तरह से सोचें, न !exit(0)तो टाइप त्रुटि हो सकती है !$xक्योंकि न तो टाइप किया जाता है।
इकेगामी

11
@ हसन, भाषा के प्रकार हैं। विशेष रूप से, मानों के प्रकार होते हैं। ऑपरेटर और उप-प्रकार केवल विशिष्ट प्रकार के मानों को लौटाने तक ही सीमित नहीं हैं। यह कम लागत (चेतावनियों के लिए धन्यवाद) में बहुत उपयोगी है।
इकेगामी

6
@ नवाज़, यह वास्तव में काफी लोकप्रिय है। यह सभी कि जावा और सी ++ में निर्माणों वस्तुओं, और पर्ल प्रोग्रामर कि का उपयोग करता है की एक बड़ी शरीर द्वारा प्रयोग किया जाता है new Classऔर print $fh ...के बजाय Class->new(...)और $fh->print(...)। मैं आपको अनुदान दूंगा कि यह एक अजीब त्रुटि संदेश का कारण बनता है, हालांकि
ikegami

112

मुझे पता नहीं क्यों, लेकिन यह वही है जो पर्ल इसका बनाता है:

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

ऐसा लगता है कि पार्सर सोचता है कि आप विधि Syntaxको error-object पर बुला रहे हैं ... अजीब बात है!


3
यह अप्रत्यक्ष विधि कॉल सिंटैक्स है। यह यहाँ काम कर रहा है (क्योंकि) exit(0)पहले मूल्यांकन किया जाता है, क्योंकि इससे पहले कि यह परिणाम पारित करने की कोशिश करता है कार्यक्रम से बाहर निकलें 'error'->Syntax()
डस्कवफ-एक्टिव-

6
पर्ल को "अप्रत्यक्ष (वस्तु) सिंटैक्स" लगता है, आमतौर पर new Classइसके बजाय इसका उपयोग किया जाता है Class->new()। विधि को कॉल करने के लिए Syntax, exitफ़ंक्शन निष्पादित किया जाता है, इसलिए रन-टाइम त्रुटि कभी नहीं होती है।
आमोन

118
बधाई हो। आपको एक ऐसा कार्यक्रम मिला जिसमें आपको अर्ध-उपनिवेश जोड़ने की आवश्यकता है ताकि असफल होने का संकलन मिल सके।
भीड़

use strict; use warnings; error->Syntax(! print "hi"); पैदावार: Perl -MO = के रूप में अच्छी तरह से सिंटैक्स ठीक है, लेकिन इसके साथ use warningsशायद कुछ कहना चाहिए क्योंकि यह पता लगा सकता है कि इसका लोड नहीं किया जा रहा है। इसके बजाय यह एक रनटाइम त्रुटि फेंकता है "ऑब्जेक्ट विधि का पता नहीं लगा सकता है .."।

53

आपको त्रुटि नहीं मिलने का कारण यह है कि पहला निष्पादित कोड है

exit(0);

क्योंकि आपके पास पहली पंक्ति में अर्धविराम नहीं था:

Syntax error!

संकलक अनुमान लगाएगा (गलत तरीके से) कि यह एक सबरूटीन कॉल है जिसमें एक notऑपरेटर को !फेंक दिया गया है। यह तब इस सबरूटीन के तर्कों को निष्पादित करेगा, जो कि होता है exit(0), जिस बिंदु पर कार्यक्रम बाहर निकलता है और 0. के लिए त्रुटि सेट करता है। , इसलिए अधिक रनटाइम त्रुटियों की सूचना नहीं है।

आप ध्यान देंगे कि यदि आप exit(0)किसी चीज़ में बदलाव करते हैं जैसे print "Hello world!"आपको कोई त्रुटि मिलती है:

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

और आपका त्रुटि स्तर सेट किया जाएगा:

> echo %errorlevel%
255

7
>The compiler will guess (incorrectly) कंपाइलर गलत तरीके से कुछ भी नहीं कर सकता है।
लियाम लावर्टी

14
@LiamLaverty हाँ, यह कर सकते हैं। यह गलत अनुमान लगा सकता है कि मानव का क्या मतलब है।
टीएलपी

4
मानव समीकरण में गलत है। कंपाइलर केवल "सही" या "टूटा हुआ" हो सकता है। इसे भाषा की परिभाषा या उपयोगकर्ता के इरादे पर एक राय नहीं मिलती है।
लियाम लावर्टी

4
अगर यह इस मामले में उपयोगकर्ता के इरादे का अनुमान लगा सकता है, तो @LiamLaverty यह एक बहुत साफ संकलक होगा। इसलिए, कंपाइलर सही अनुमान नहीं लगा सकता है। आप मेरे बयान का कुछ तकनीकी विश्लेषण कर सकते हैं, जो कि, मैं इसे पढ़ने का गलत तरीका जोड़ सकता हूं।
टीएलपी

क्या यह एक व्याख्याकार नहीं है? ;-)
रिक्की

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

इस पत्र में , हम प्रोग्रामिंग भाषाओं समुदाय में एक लंबे समय से खुली समस्या का जवाब देने का लक्ष्य रखते हैं: क्या वैध पर्ल बनाए बिना दीवार पर पेंट को धब्बा करना संभव है?

TLDR; मुश्किल से


मुझे वह अच्छा लगता है। मुझे कुछ चित्रों में स्कैन करना पड़ सकता है।
बिल रुपेर्ट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.