लूप के लिए अर्धविराम और अल्पविराम परस्पर क्यों जुड़े हैं?


49

कई भाषाओं में (C से जावास्क्रिप्ट तक एक विस्तृत सूची):

  • अल्पविराम ,अलग तर्क (जैसे func(a, b, c)), जबकि
  • अर्धविराम ;अलग अनुक्रमिक निर्देश (जैसे instruction1; instruction2; instruction3)।

तो क्यों यह मैपिंग छोरों के लिए समान भाषाओं में उलट दी गई है :

for ( init1, init2; condition; inc1, inc2 )
{
    instruction1;
    instruction2;
}

इसके बजाय (जो मुझे अधिक स्वाभाविक लगता है)

for ( init1; init2, condition, inc1; inc2 )
{
    instruction1;
    instruction2;
}

?

बेशक, forहै (आमतौर पर) नहीं एक समारोह है, लेकिन तर्क (यानी init, condition, increment) और अधिक निर्देश के अनुक्रम की तुलना में एक समारोह के तर्कों की तरह व्यवहार करते हैं।

यह ऐतिहासिक कारणों / एक सम्मेलन की वजह से वहाँ का आदान-प्रदान के लिए एक अच्छा तर्क है, या है ,और ;छोरों में?


1
(। मेरे f1rst पोस्ट यहाँ मुझे यकीन है कि इस सवाल का प्रोग्रामर्स के लिए और अधिक अंतर्गत आता है या तो, तो, विस्थापित करने के लिए स्वतंत्र लग रहा है, तो यह आवश्यक है कि क्या नहीं कर रहा हूँ।)
पिओर Migdal

8
यह निश्चित रूप से एक प्रोग्रामर पोस्ट है। स्वागत हे! :-)
मार्टिज़न पीटरर्स

1
"व्हाई नॉट" एक ही उत्तर होने से उत्तर प्रदान करेगा - "क्योंकि किसी को एक विकल्प बनाने की आवश्यकता थी, और वह विकल्प है कि उन्होंने" समान के रूप में "क्यों" उन्होंने "{" और "} का चयन किया और 1000 अन्य विकल्प चुने। उन्होंने बनाया - "क्योंकि"।
मटनज़

2
@mattnz प्रश्न सुसंगतता के बारे में है ("हम क्यों ;नहीं उपयोग करते हैं |?" (या हम 'अन्य' का उपयोग 'नहीं' अन्यथा क्यों करते हैं? )) जो एक भाषा के लिए मामला नहीं है, लेकिन उनमें से एक बड़ी संख्या है। एक जवाब है कि उदाहरण के लिए "यह सी में शॉर्टहैंड के रूप में बनाया गया था जबकि लूप (और इंक के लिए कई बयान केवल बाद में सोचा गया था), और लोग इसे प्रोग्रामर की जलन से बचने के लिए इसे बदलना नहीं चाहते थे" पूरी तरह से ठीक होगा।
पियोत्र मिग्डल

मुझे पढ़ना याद है - शायद K & R में - कि कॉमा ऑपरेटर को मूल रूप से भाषा में जोड़ा गया था ताकि यह कथन के लिए init-अभिव्यक्ति में एक से अधिक वेरिएबल को इनिशियलाइज़ कर सके।
zwol

जवाबों:


18

तो क्यों समान भाषाओं में लूप्स के लिए ऐसी मैपिंग को उलट दिया जाता है।

तकनीकी रूप से, मैपिंग "उलट" नहीं है।

  • अल्पविराम द्वारा अलग की गई चीजें पैरामीटर नहीं हैं। (कम से कम) सी ++ और जावा में, वे घोषणाएं हो सकती हैं, इसलिए वे भी अभिव्यक्ति नहीं हैं।
  • अर्धविराम द्वारा अलग की गई चीजें (एकल) कथन नहीं हैं।

वास्तव में हमारे यहाँ जो कुछ है, वह एक अलग वाक्य-विन्यास है जहाँ समान प्रतीकों का अलग-अलग उपयोग किया जा रहा है। हम जैसे के साथ तुलना नहीं कर रहे हैं, इसलिए कोई मैपिंग नहीं है, और अर्थ संगति के आधार पर लगातार मैपिंग के लिए कोई मजबूत तर्क नहीं है।

तो इसे दूसरे तरीके से क्यों न करें?

खैर मुझे लगता है कि कई कारणों से "प्राकृतिक" अर्थ से आते हैं ,और ;। अंग्रेजी लिखित भाषा में, अर्धविराम अल्पविराम से "अधिक मजबूत" होता है, और अर्धविराम के लिए ग्लिफ़ अल्पविराम की तुलना में अधिक दिखाई देता है। उन दो चीजों को वर्तमान व्यवस्था बनाने के लिए जोड़ते हैं (मुझे!) अधिक प्राकृतिक होने के लिए।

लेकिन यह सुनिश्चित करने का एकमात्र तरीका है कि वाक्यविन्यास पसंद क्यों किया गया था यदि सी डिजाइनर हमें बता सकते हैं कि वे ~ 1970 में वापस क्या सोच रहे थे। मुझे संदेह है कि उनके पास तकनीकी निर्णयों की स्पष्ट स्मृति है जो समय में बहुत पीछे चले गए।


क्या यह ऐतिहासिक कारणों / एक सम्मेलन के कारण है

मुझे C से पहले किसी भी भाषा के बारे में पता नहीं है जो "छोरों" के लिए "के लिए एक सी-सिंटैक्स" का उपयोग करता है:

  • डोनल फेलो ने ध्यान दिया कि BCPL और B में एक समतुल्य निर्माण नहीं था।

  • FORTRAN, COBOL और Algol-60 (और पास्कल) समकक्ष कम अभिव्यंजक थे, और उनमें सिंटैक्स थे जो "सिंटैक्स" के लिए C "के समान नहीं थे।

लेकिन C के बाद आई C, C ++ और Java जैसी भाषाएं स्पष्ट रूप से C से "सिंटैक्स" के लिए अपना "उधार" लेती हैं।


तो, ( ,बनाम ;) का दर्शन (कमजोर बनाम मजबूत तोड़) है, बजाय (टपल-बनाम अनुक्रम-फाड़नेवाला), सही? अभी भी मेरे लिए यह स्पष्ट नहीं है कि क्या तर्कों या बयानों को मजबूत विराम की आवश्यकता होती है (जैसा कि कई मामलों में बयानों के अनुक्रम के लिए होता है, विराम अंतर्निहित होते हैं (उदाहरण के लिए जावास्क्रिप्ट (उदा i++[line break]j++)) देखें), लेकिन कम से कम अब मुझे वह मुद्दा मिल गया है कि वर्तमान सम्मेलन क्यों "स्पष्ट रूप से उलट" नहीं है।
पियोत्र मिग्डल

@PiotrMigdal अल्पविराम के रूप में अल्पविराम अल्पविराम के उपयोग को रोक सकता है और हो सकता है कि लूप के घटक अभिव्यक्ति के बजाय बयान हों। इसके महत्वपूर्ण निहितार्थ हैं।

आखिरी टिप्पणी ने मुझे उत्सुक किया कि बीसीपीएल ने क्या किया, लेकिन जाहिर है कि यह वहाँ था FOR i = e1 TO e2 BY e3 DO c(e1..e3 अभिव्यक्ति, सी कमांड), जो अधिक बारीकी से बेसिक के सिंटैक्स जैसा दिखता है। स्रोत
एक CVn

1
@PiotrMigdal - "दर्शन" जो कुछ भी K & R है और बाकी सभी 1970 में वापस सोच रहे थे। मुझे नहीं लगता कि यह सोच की गहराई तक गया था कि आप कल्पना करते हैं। (वे असेंबलर में टेलीफोन स्विच सॉफ्टवेयर के द्रव्यमान को लिखने से बचने के लिए "उच्च स्तर" की भाषा को लागू करने की कोशिश कर रहे थे।)
स्टीफन C

मैंने अभी जाँच की; forवाक्य रचना (यह में नहीं था सी में पेश किया गया था बी या BCPL)।
डोनल फैलो

60

हम लूप लिखते हैं जैसे:

 for(x = 0; x < 10; x++)

भाषा को परिभाषित किया जा सकता था ताकि छोरों की तरह दिखे:

 for(x = 0, x < 10, x++)

हालाँकि, एक ही लूप का उपयोग करके लागू किए गए समान लूप के बारे में सोचें:

 x = 0;
 while(x < 10)
 {
     x++;
 }

ध्यान दें कि x=0और x++बयानों को अर्धविराम से समाप्त हो गया है। वे ऐसे नहीं हैं जैसे आप एक फ़ंक्शन कॉल में हैं। अर्धविराम का उपयोग बयानों को अलग करने के लिए किया जाता है, और चूंकि लूप के लिए तीन में से दो तत्व कथन हैं, इसलिए वहां इसका उपयोग किया जाता है। लूप के लिए एक लूप थोड़ी देर के लिए एक शॉर्टकट है।

इसके अतिरिक्त, तर्क वास्तव में किसी फ़ंक्शन के लिए तर्क की तरह कार्य नहीं करते हैं। दूसरे और तीसरे का बार-बार मूल्यांकन किया जाता है। यह सच है कि वे एक अनुक्रम नहीं हैं, लेकिन वे भी कार्य तर्क नहीं हैं।

इसके अलावा, इस तथ्य के लिए कि आप लूप के लिए कई कथनों के लिए अल्पविराम का उपयोग कर सकते हैं वास्तव में कुछ ऐसा है जो आप लूप के लिए कर सकते हैं।

x = 0, y= 3;

लूप के बाहर भी पूरी तरह से मान्य कथन है। मैं हालांकि लूप के लिए किसी भी व्यावहारिक उपयोग के बारे में नहीं जानता। लेकिन मुद्दा यह है कि अल्पविराम हमेशा बयानों को तोड़ता है; यह लूप की खास विशेषता नहीं है।


ज़रूर, मैं समझता हूँ कि "जबकि" लूप "अधिक मौलिक" है। लेकिन इस तरह के "शॉर्ट-हैंड नोटेशन" का ज्यादा मतलब नहीं है (कम से कम मेरे लिए), जैसा कि आप शुरू कर सकते हैं x = 0; y = 0;और (घुंघराले ब्रैकेट के अंदर) x++; y++;...
पिओटर मिग्डल

2
@PiotrMigdal, ओह तुम कर सकते थे। मेरा कहना है कि लूप के लिए टुकड़े स्टेटमेंट हैं (जो अर्धविराम द्वारा अलग किए गए हैं) एक्सप्रेशन नहीं (जो कॉमा द्वारा अलग किए गए हैं)
विंस्टन इवर्ट

1
मुझे अंतर मिलता है, बस मेरे ;लिए बयानों के अनुक्रम के लिए स्वाभाविक है , जरूरी नहीं कि किसी भी बयान को अलग करना (इसलिए क्या यह सिर्फ स्वाद अलग है?)। और वर्तमान अधिवेशन में कभी-कभार वैसे भी अल्पविरामों के साथ बयानों के अनुक्रम को अलग करने के साथ समाप्त होता है ...
पिओत्र मिग्डल

3
@PiotrMigdal, स्ट्रक्चर / यूनियनों के सदस्यों को अर्धविराम द्वारा अलग किया जाता है, लेकिन वे वास्तव में अनुक्रमिक नहीं हैं। तो निश्चित रूप से इसके उपयोग में बयान के एक अनुक्रम तक ही सीमित नहीं है। दिन के अंत में, सिंटैक्स स्वाद के लिए नीचे आता है।
विंस्टन इवर्ट

मैं पाश के लिए किसी भी व्यावहारिक उपयोग के बारे में नहीं जानता, हालांकि --- कैसे के बारे में (foo)?bar++, qux++:bletch--- जहाँ आप चाहते हैं कि ?:अभिव्यक्ति केवल एक के बजाय दो चीजें करें। वापसी मान यदि fooसत्य है qux, लेकिन दोनों barऔर quxवृद्धि की जाती मिलता है।

15

C और C ++ में यह अल्पविराम ऑपरेटर है, न कि केवल एक अल्पविराम।

एक forलूप के लिए व्याकरण कुछ इस तरह है

for ([pre-expression]; [terminate-condition]; [increment-expression]) body-expression

आपके प्रश्न के मामले में:

pre-expression -> init1, init2
terminate-condition -> condition
increment-expression -> inc1, inc2

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

संक्षेप में, ;एक बयान के अंत का प्रतीक है। एक forलूप एक खोजशब्द है जिसके बाद वैकल्पिक विवरणों की एक सूची होती है ()। अल्पविराम-संचालक कथन ,एक कथन में उपयोग की अनुमति देता है ।


3
लूप के लिए अर्धविराम द्वारा अलग किए गए भावों का एक समूह है। कथन अभिव्यक्ति की तुलना में बहुत अधिक हो सकते हैं - कोई केस स्टेटमेंट या यदि लूप भागों के लिए स्टेटमेंट को स्लिप नहीं कर सकता है। यह कहना महत्वपूर्ण है कि लूप के घटक एक स्टेटमेंट हैं जब कोई लूप के लिए bnf फॉर्म को

@ मिचेल्ट: लेकिन सी ++ में एक forलूप का वाक्यविन्यास स्पष्ट रूप से एक बयान (घोषणा) को इसके पहले भाग के रूप में अनुमति देता है। (C ++ ने मिड-फंक्शन की घोषणा की अनुमति दी, जैसा कि इसके पूर्ववर्ती C89 के विपरीत है)। आप C और C ++ की तरह 2 भाषाओं के लिए भी, इस तरह के बयानों को सामान्य नहीं कर सकते।
MSalters

@ मिचेल्ट क्या आपने 'भाग जैसा कुछ है' को याद किया?
जेम्स

@James आप की वास्तविक BNF का उपयोग करके "की तरह कुछ" से बच सकते हैं for ( {<expression>}? ; {<expression>}? ; {<expression>}? ) <statement>के लिए सी और for ( for-init-statement; conditionopt ; expressionopt ) statementके लिए सी ++ --- ';' केवल एक बयान टर्मिनेटर का संकेत नहीं है। लूप के लिए () () में दिए गए कथनों का पालन नहीं किया जाता है।

8

कोई वैचारिक उलटफेर नहीं है।

सी में अर्धविराम अल्पविराम से अधिक प्रमुख विभाजनों का प्रतिनिधित्व करते हैं। वे बयानों और घोषणाओं को अलग करते हैं।

लूप के लिए प्रमुख विभाजन यह है कि तीन भाव हैं (या एक घोषणा और दो भाव) और एक शरीर।

लूप्स के लिए C में आप जो कॉमा देखते हैं, वे विशेष रूप से लूप के सिंटैक्स का हिस्सा नहीं हैं। वे सिर्फ अल्पविराम ऑपरेटर की अभिव्यक्तियाँ हैं।

फ़ंक्शन कॉल में तर्कों के बीच और फ़ंक्शन घोषणाओं में मापदंडों के बीच कॉमा प्रमुख विभाजक हैं, लेकिन अर्धविराम का उपयोग नहीं किया जाता है। लूप के लिए विशेष वाक्यविन्यास है; यह फ़ंक्शन या फ़ंक्शन कॉल से कोई लेना-देना नहीं है।


2

हो सकता है कि यह C / C ++ के लिए कुछ विशिष्ट है, लेकिन मैं इस उत्तर को पोस्ट करता हूं, क्योंकि आपके द्वारा वर्णित अंतराल के सिंटैक्स ज्यादातर सी-सिंटैक्स से प्रभावित होते हैं।

पहले से उत्तरित प्रश्नों के अलावा, तकनीकी दृष्टिकोण से, यह सच है, क्योंकि C (और C ++) में अल्पविराम वास्तव में एक ऑपरेटर है , जिसे आप ओवरलोड भी कर सकते हैं । अर्धविराम-ऑपरेटर ( operator;()) का उपयोग करने से संभवतः कंपाइलर्स लिखना कठिन हो जाएगा, क्योंकि अर्धविराम एक्सिओमेटिक अभिव्यक्ति टर्मिनेटर है।

यह अंतरविरोध क्या है, यह तथ्य है, कि अल्पविराम का उपयोग भाषा में सेपरेटर के रूप में व्यापक रूप से किया जाता है । ऐसा लगता है कि अल्पविराम ऑपरेटर एक अपवाद है, जिसका उपयोग मुख्य रूप से forकई स्थितियों के साथ-साथ काम करने की स्थिति के लिए किया जाता है , तो सौदा क्या है?

वास्तव में operator,इसे समान कार्य करने के लिए बनाया गया है जैसे परिभाषाएँ, तर्क सूचियाँ, और इसी तरह: इसका निर्माण अभिव्यक्ति को अलग करने के लिए किया गया है - कुछ ऐसा जो वाक्यात्मक निर्माण ,नहीं कर सकता है। यह केवल वही अलग कर सकता है जो मानक में परिभाषित किया गया है।

हालांकि अर्धविराम अलग नहीं होता है - यह समाप्त हो जाता है । और यह वही है जो हमें मूल प्रश्न पर वापस ले जाता है:

for (int a = 0, float b = 0.0f; a < 100 && b < 100.0f; a++, b += 1.0f)
    printf("%d: %f", a, b);

अल्पविराम तीन लूप भागों में अभिव्यक्तियों को अलग करता है, जबकि अर्धविराम लूप परिभाषा का एक हिस्सा (आरंभीकरण, स्थिति या बाद में) समाप्त करता है।

नई प्रोग्रामिंग भाषाओं (जैसे C #) कोमा-ऑपरेटर को अधिभारित करने की अनुमति नहीं दे सकती है, लेकिन उन्हें सबसे अधिक संभावना सिंटैक्स रखने की है, क्योंकि इसे बदलना किसी तरह अप्राकृतिक लगता है।


इस तर्क के साथ एक समस्या है। एक forबयान में ;प्रतीक को स्पष्ट रूप से एक विभाजक के रूप में उपयोग किया जाता है। यह कथन के 3 सिंटैक्टिक भागों को अलग करता है। प्रगतिशील अभिव्यक्ति सूची को "समाप्त" करने के लिए तीसरा अर्धविराम नहीं है। इसे एक अलग टोकन द्वारा समाप्त किया जाता है - )
स्टीफन C

0

मेरे लिए वे अपनी भाषाई समझ के लिए कम समान अर्थ का उपयोग करते हैं। कॉमेस का उपयोग सूचियों और अर्धविरामों के साथ किया जाता है जिसमें अधिक अलग भाग होते हैं।

में func(a, b, c)हम तर्क की एक सूची है।

instruction1; instruction2; instruction3 शायद एक सूची है, लेकिन अलग और स्वतंत्र निर्देशों की एक सूची है।

जबकि for ( init1, init2; condition; inc1, inc2 )हमारे पास तीन अलग-अलग भाग हैं - इनिशियलाइज़ेशन की एक सूची, एक शर्त और वेतन वृद्धि के भावों की एक सूची।


0

इसे देखने का सबसे आसान तरीका निम्नलिखित है:

for(x = 0; x < 10; x++)

है:

for(
x = 0;
x < 10;
x++
)

दूसरे शब्दों में, उन x = 0 thingy वास्तव में एक पैरामीटर के बजाय एक बयान / निर्देश है। आप वहां एक स्टेटमेंट डालें। इसलिए उन्हें अर्धविराम द्वारा अलग किया जाता है।

वास्तव में वहाँ कोई रास्ता नहीं है कि वे अल्पविराम से अलग हो जाते हैं। अंतिम बार जब आप x <10 जैसी चीजों को एक पैरामीटर के रूप में सम्मिलित करते हैं? यदि आप एक बार कंप्यूटर x <10 चाहते हैं और पैरामीटर के रूप में उस ऑपरेशन का परिणाम डालें। तो अगर आप एक समारोह में x <0 के मूल्य पर पारित करना चाहते हैं तो अल्पविराम दुनिया में आप x <10 डालेंगे।

यहां आप निर्दिष्ट करते हैं कि प्रोग्राम को हर बार लूप पास होने पर x <10 की जांच करनी चाहिए। तो यह एक निर्देश है।

x ++ निश्चित रूप से एक और निर्देश है।

वे सभी निर्देश हैं। इसलिए वे अर्ध उपनिवेश द्वारा अलग हो जाते हैं।


यह एक बयान नहीं है। यह एक अर्धविराम से अलग एक अभिव्यक्ति है। एक कथन पूरी तरह से अलग है।

x <10 एक अभिव्यक्ति हो सकती है (जिसे आमतौर पर अर्धविराम द्वारा अलग किया जाएगा। x = 0 निश्चित रूप से एक कथन / निर्देश है।
user4951

को देखो सी के लिए BNF - अगर पाश बयान था के लिए, ऐसे ही एक दूसरे के रूप में अन्य बयान इस्तेमाल कर सकते हैं for switchया return अंदर पाश परिभाषा (यानी के लिए for(int i = 0; if(i > 1024) { return; } ; switch (i % 3) { case 0; case 1: i++; case 2: i++; } ) { ... }) --- आप नहीं कर सकते। यह एक बयान नहीं है। इसके बजाय इसे परिभाषित किया गया हैfor ( {<expression>}? ; {<expression>}? ; {<expression>}? ) <statement>

अजीब। int i = 0 एक अभिव्यक्ति है, लेकिन हम इसे मुख्य रूप से int घोषित करने के लिए करते हैं, और इसे 0 पर असाइन करते हैं (यह 0 भी देता है, लेकिन साइड इफेक्ट के रूप में। आप ऐसा नहीं कर सकते ({int i = 0); j = i}; j <0; cout << "हैलो वर्ल्ड") आप कर सकते हैं? या हाँ मुझे लगता है कि आप कर सकते हैं।
user494951

1
@JimThio: आप शायद इसके बारे में नहीं जानते हैं, लेकिन "कथन" और "अभिव्यक्ति" भाषा के मानकों में बहुत सटीक अर्थ हैं। int i = 0निश्चित रूप से एक अभिव्यक्ति नहीं है। एक अभिव्यक्ति का वर्णन करने वाले नियमों का सेट काफी जटिल है, यह देखते हुए कि एक अभिव्यक्ति क्या हो सकती है, लेकिन निर्माण TYPE NAME = EXPRESSIONउन नियमों में से किसी से मेल नहीं खाता है।
MSalters
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.