प्रयास करने के लिए कोष्ठक क्यों आवश्यक हैं?


38

विभिन्न भाषाओं में (जावा कम से कम, यह भी सोचें C #?) आप जैसे काम कर सकते हैं

if( condition )
    singleStatement;

while( condition )
    singleStatement;

for( var; condition; increment )
    singleStatement;

इसलिए जब मेरे पास सिर्फ एक बयान है, तो मुझे एक नया दायरा जोड़ने की जरूरत नहीं है { }। मैं कोशिश-कैच के साथ ऐसा क्यों नहीं कर सकता?

try
    singleStatement;
catch(Exception e)
    singleStatement;

क्या ट्राइ-कैच के बारे में कुछ खास है जिसके लिए हमेशा नया स्कोप होना चाहिए या कुछ और होना चाहिए? और यदि ऐसा है, तो संकलक ठीक नहीं कर सकता है?


3
यहाँ नाइट-पिकिंग: forभागों के लिए कड़ाई से बोलने का नाम कुछ ऐसा होना चाहिए initial, conditionऔर stepजैसा initialकि एक चर को परिभाषित करने की stepआवश्यकता नहीं है और आवश्यकता नहीं है।
जोकिम सॉउर

4
एक साइड नोट के रूप में D को एकल स्टेटमेंट को पकड़ने की कोशिश करने के लिए ब्रेसिज़ की आवश्यकता नहीं है
शाफ़्ट फ्रीक

13
मुझे लगता है कि असली सवाल दूसरा रास्ता है: कुछ निर्माण "नग्न" बयानों की अनुमति क्यों देते हैं? स्थिरता के लिए ब्रेसिज़ को हर जगह अनिवार्य होना चाहिए।
अंकलज़ेव

3
@UncleZeiv - यदि आप इस बात पर विचार नहीं करते हैं कि यह असंगत नहीं है, तो ifयह हमेशा एक एकल कथन है, और ब्रेसिज़ द्वारा दिए गए कई बयानों में एक ही कथन शामिल है। लेकिन मैं जो लोग हमेशा में वैसे भी, तो ब्रेसिज़ डाल में से एक हूँ ...
detly

1
मैं अच्छी तरह से ब्रेसिज़ लिखने के लिए करते हैं, लेकिन मैं उन्हें लिखने के लिए जब मैं की तरह सीधा निकास बिंदुओं केवल सहायता की जरूरत नहीं पसंद throwऔर return, और की तरह @detly कहा, यदि आप बयान के एक समूह के रूप में ब्रेसिज़ पर विचार, मैं इसे नहीं पाते असंगत भी। मैंने कभी नहीं समझा कि लोगों द्वारा बताई गई ये "बहुत सारी कोडिंग त्रुटियां" क्या हैं। लोगों को इस बात पर ध्यान देने की आवश्यकता है कि वे क्या करते हैं, उचित संकेत का उपयोग करें और यूनिट परीक्षण करें: पी को इस से कोई समस्या नहीं थी ...
Svish

जवाबों:


23

IMO, वे जावा और C # में मुख्य रूप से शामिल हैं क्योंकि वे पहले से ही C ++ में मौजूद थे। वास्तविक प्रश्न, फिर, C ++ ऐसा क्यों है। सी + + ()16.3) के डिजाइन और विकास के अनुसार :

tryकीवर्ड पूरी तरह से बेमानी है और इसलिए कर रहे हैं { }, जहां कई बयान वास्तव में एक कोशिश ब्लॉक या हैंडलर में किया जाता है को छोड़कर कोष्ठक। उदाहरण के लिए, यह अनुमति देने के लिए तुच्छ होगा:

int f()
{
    return g() catch(xxii) { // not C++
        error("G() goofed: xxii");
        return 22;
    };
}

हालांकि, मुझे यह समझाने में इतनी मुश्किल हुई कि समर्थन कर्मियों को भ्रमित उपयोगकर्ताओं से बचाने के लिए अतिरेक पेश किया गया था।

संपादित करें: जैसा कि यह भ्रामक होगा, इसलिए मुझे लगता है कि किसी को @Tom जेफरी के उत्तर (और विशेष रूप से, अप-वोटों की संख्या जो प्राप्त हुई है) में गलत दावे को देखने के लिए यह महसूस करना होगा कि कोई समस्या होगी। पार्सर के लिए, यह वास्तव में elseएस के साथ मेल खाने वाले एस से अलग नहीं है if- अन्य समूह को मजबूर करने के लिए ब्रेसिज़ की कमी है, सभी catch खंड सबसे हाल के साथ मेल खाएंगे throw। उन दुर्व्यवहारों के लिए जो इसमें शामिल हैं, finallyखंड एक ही करेंगे। पार्सर के दृष्टिकोण से, यह शायद ही वर्तमान स्थिति से नोटिस करने के लिए अलग-अलग है - विशेष रूप से, क्योंकि व्याकरण अब खड़ा है, वहाँ वास्तव में catchएक साथ खंडों को समूह करने के लिए कुछ भी नहीं है - ब्रैकेट समूह द्वारा नियंत्रित कथनों का समूहcatch खंड, नहीं पकड़ खुद को रोक देता है।

एक पार्सर लिखने के दृष्टिकोण से, अंतर लगभग नोटिस करने के लिए बहुत छोटा है। अगर हम कुछ इस तरह से शुरू करते हैं:

simple_statement: /* won't try to cover all of this */
                ;

statement: compound_statement
         | simple_statement
         ;

statements: 
          | statements statement
          ;

compound_statement: '{' statements '}'

catch_arg: '(' argument ')'

तब अंतर इस प्रकार होगा:

try_clause: 'try' statement

तथा:

try_clause: 'try' compound_statement

इसी तरह, क्लॉस पकड़ने के लिए:

catch_clause: 'catch' catch_arg statement

बनाम

catch_clause: 'catch' catch_arg compound_statement

एक पूर्ण कोशिश / कैच ब्लॉक की परिभाषा को हालांकि बिल्कुल भी बदलने की आवश्यकता नहीं होगी। किसी भी तरह से यह कुछ इस तरह होगा:

catch_clauses: 
             | catch_clauses catch_clause
             ;

try_block: try_clause catch_clauses [finally_clause]
         ;

[यहां मैं [whatever]कुछ वैकल्पिक इंगित करने के लिए उपयोग कर रहा हूं , और मैं वाक्य रचना को छोड़ रहा हूं finally_clauseक्योंकि मुझे नहीं लगता कि इसका प्रश्न पर कोई असर है।]

यहां तक ​​कि अगर आप वहां सभी Yacc जैसी व्याकरण की परिभाषा का पालन करने की कोशिश नहीं करते हैं, तो बिंदु को काफी आसानी से संक्षेप में प्रस्तुत किया जा सकता है: वह अंतिम विवरण (साथ शुरू try_block) वह है जहां catchक्लॉज क्लॉज के साथ मेल खाते tryहैं - और यह वास्तव में रहता है वही ब्रेस की आवश्यकता है या नहीं।

/ संक्षेप दोहराना करने के लिए: ब्रेसिज़ समूह को एक साथ नियंत्रित बयानों सेcatch है, लेकिन ऐसा नहीं समूह catchखुद को है। जैसे, उन ब्रेसिज़ का निर्णय लेने पर बिल्कुल कोई प्रभाव नहीं पड़ता है जो catchकिसके साथ जाती हैं try। पार्सर / कंपाइलर के लिए कार्य समान रूप से आसान (या कठिन) है। इसके बावजूद, @ टॉम का जवाब (और इसे प्राप्त होने वाले वोटों की संख्या) इस तथ्य का पर्याप्त प्रदर्शन प्रदान करता है कि इस तरह का बदलाव उपयोगकर्ताओं को लगभग निश्चित रूप से भ्रमित करेगा


ओपी कोशिश और कैच ब्लॉक दोनों के चारों ओर कोष्ठक के बारे में पूछ रहा है , जबकि यह कोशिश के आसपास के लोगों को संदर्भित करता प्रतीत होता है (पहले पैराग्राफ को दोनों को संदर्भित करने के लिए समझा जा सकता है, लेकिन कोड केवल पूर्व दिखाता है) ... क्या आप कर सकते हैं स्पष्ट करना?
Shog9

@ Mr.CRT: "कैच ब्लॉक" अन्यथा "हैंडलर" के रूप में जाना जाएगा, जिसके बारे में उपरोक्त उद्धरण देखें।
जेरी कॉफिन

3
bah, बस उस अस्पष्टता को दूर करने के लिए मेरी टिप्पणी संपादित की । मुझे जो मिल रहा है, वह टॉम (ऊपर) की तुलना में अधिक प्रभावी उत्तर हो सकता है यदि यह वर्णन करने के लिए अधिक लंबाई तक गया कि ब्रैकेट-कम निर्माण कैसे काम कर सकता है, लेकिन एक भ्रमित तरीके से (टॉम के जवाब पर बिली की टिप्पणी लगती है) इसका मतलब है कि यह काम नहीं कर सकता था , जो मुझे लगता है कि गलत है)।
Shog9

@JerryCoffin आपके उत्तर का विस्तार करने के लिए धन्यवाद: यह अब मेरे लिए बहुत स्पष्ट है।

try return g(); catch(xxii) error("G() goofed: xxii");
व्होल

19

एरिक लिपपार्ट ने कुछ एकल-कथन निर्माणों के लिए कोष्ठक की आवश्यकता क्यों है, इसके बारे में एक उत्तर में , एरिक लिपर्ट ने लिखा:

ऐसे कई स्थान हैं जहाँ C # को "नग्न" कथन की अनुमति देने के बजाय कथनों के लटके ब्लॉक की आवश्यकता होती है। वो हैं:

  • एक विधि, कंस्ट्रक्टर, डिस्ट्रक्टर, प्रॉपर्टी एक्सेसर, ईवेंट एक्सेसर या इंडेक्स एक्सेसर का शरीर।
  • एक कोशिश के ब्लॉक, पकड़, अंत में, जाँच, अनियंत्रित या असुरक्षित क्षेत्र।
  • एक स्टेटमेंट लैम्ब्डा या अनाम विधि का ब्लॉक
  • if या लूप स्टेटमेंट के ब्लॉक यदि ब्लॉक में सीधे एक स्थानीय चर घोषणा होती है। (वह है, "जबकि (x! = 10) int y = 123;" गैरकानूनी है; आपको घोषणा पर रोक लग गई है।)

इनमें से प्रत्येक मामले में यह सुविधा के लिए एक अस्पष्ट व्याकरण (या एक अस्पष्ट व्याकरण की अवहेलना करने के लिए उत्तराधिकार) के साथ आना संभव होगा, जहां एक एकल अटूट कथन कानूनी है। लेकिन बात क्या होगी? उन स्थितियों में से प्रत्येक में आप कई बयान देखने की उम्मीद कर रहे हैं; एकल कथन दुर्लभ, असंभावित मामला है। ऐसा लगता है कि यह व्याकरण को इन बहुत ही अप्रत्याशित मामलों के लिए अस्पष्ट बनाने के लिए वास्तव में इसके लायक नहीं है।

दूसरे शब्दों में, संकलक टीम के लिए इसे लागू करना अधिक उचित था, जो कि मामूली लाभ के लिए इसे प्रदान करेगा।


13

मुझे लगता है कि इसे स्टाइल के अन्य मुद्दों को टालने से बचना चाहिए। निम्नलिखित अस्पष्ट होगा ...

try
    // Do stuff
try
    // Do  more stuff
catch(MyException1 e1)
    // Handle fist exception
catch(MyException2 e2)
    // So which try does this catch belong to?
finally
    // and who does this finally block belong to?

इसका मतलब यह हो सकता है:

try {
   try {

   } catch(Exception e1) {

   } catch(Exception e2) {

   } 
} finally {

} 

या ...

try {
   try {

   } catch(Exception e1) {

   } 
} catch(Exception e2) {

} finally {

} 

24
इस अस्पष्टता के लिए लागू होता है, तो और के लिए समान रूप से। सवाल है: ऐसा क्यों है कि यह अनुमति दी है के लिए अगर और स्विच बयान लेकिन के लिए नहीं ट्राई / कैच ?
दीपन मेहता

3
@ दिपन मेला। मुझे आश्चर्य है कि अगर यह केवल जावा / सी # की बात है तो गैर-लटके हुए आईएफ की अनुमति देकर सी जैसी पुरानी भाषाओं के अनुरूप होने की कोशिश की जाती है। जबकि कोशिश / पकड़ एक नया निर्माण है, इसलिए भाषा डिजाइनरों ने परंपरा के साथ तोड़ना ठीक समझा।
टॉम जेफरीज़

मैंने कम से कम C और C ++ के लिए मजबूरी का जवाब देने की कोशिश की।
दीपन मेहता

6
@DipanMehta: क्योंकि ifमामले के लिए कई संभावित लटकने वाले खंड नहीं हैं । यह कहना आसान है "अच्छी तरह से अगर अंतरतम के लिए बाध्य करता है" और इसके साथ किया जाए। लेकिन कोशिश / पकड़ के लिए जो काम नहीं करता है।
बिली ओनली

2
@ बिली: मुझे लगता है कि आप अगर / यदि मौजूद हैं तो संभावित अस्पष्टता पर चमक रहे हैं ... यह कहना आसान है "यह सिर्फ कहना आसान है" - लेकिन ऐसा इसलिए है क्योंकि अस्पष्टता को हल करने के लिए एक कठिन नियम है जो, संयोगवश, विघटन करता है कोष्ठक के उपयोग के बिना कुछ निर्माण। जेरी का जवाब है कि यह भ्रम से बचने के लिए किया गया एक सचेत विकल्प था, लेकिन निश्चित रूप से यह काम कर सकता था - ठीक वैसे ही जैसे कि अगर यह "काम करता है"।
Shog9

1

मुझे लगता है कि इसका मुख्य कारण यह है कि C # में बहुत कम आप कर सकते हैं जिसे एक कोशिश / कैच ब्लॉक की आवश्यकता होगी जो केवल एक लाइन है। (मैं अपने सिर के शीर्ष पर अभी किसी के बारे में नहीं सोच सकता)। आपके पास कैच ब्लॉक के संदर्भ में एक मान्य बिंदु हो सकता है, जैसे कि किसी चीज़ को लॉग करने के लिए एक लाइन स्टेटमेंट लेकिन पठनीयता के संदर्भ में इसे {} की आवश्यकता के लिए अधिक समझ में आता है (कम से कम मेरे लिए)।

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