पीछे हटने वाला व्याकरण बयान के एक शरीर के बीच एक ज्ञात अस्पष्टता उत्पन्न करता है (आपके मामले में, यह for
लूप है, लेकिन यह अन्य कथनों पर भी लागू होता है) और पिछला बंद करने का शरीर। हालांकि यह इस समस्या, compiler designers decided to prohibit trailing closure syntax in controlling portions of various high-level statements हल करने के लिए तकनीकी रूप से संभव है:
While it would be possible to tell what is intended in some cases by performing arbitrary lookahead or by performing type checking while parsing, these approaches have significant consequences for the architecture for the compiler. As such, we've opted keep the parser simple and disallow this.
संघर्ष की प्रकृति को समझने के लिए, इस उदाहरण पर विचार करें:
for v in expr { /* code 1 */ } { /* code 2 */ }
पार्सर code 1
ब्लॉक के बारे में एक विकल्प बनाने की जरूरत है। यह या तो expr
के अनुगामी बंद के रूप में उपयोग कर सकते हैं और for
लूप के शरीर के रूप में code 2
का इलाज, या for
लूप के शरीर के रूप में code 1
उपयोग करते हैं, जबकि घुंघराले ब्रेसिज़ में संलग्न बयान के एक स्वतंत्र समूह के रूप में code 2
इलाज - एक क्लासिक shift-reduce conflict ।
ऐसे संघर्षों को हल करना बहुत महंगा है। अनिवार्य रूप से, आपके पार्सर को अधिक टोकन के माध्यम से आगे बढ़ना जारी रखना चाहिए, जब तक केवल एक व्याख्या समझ में न हो, या पार्सर टोकन से बाहर हो जाता है (इस मामले में यह एक मनमाने ढंग से निर्णय एक तरफ या दूसरे बनाता है, जिसके लिए प्रोग्रामर को अपने कार्यक्रम को असंबद्ध करने की आवश्यकता होती है वह विकल्प वह नहीं है जो वे चाहते थे)।
कोष्ठक जोड़ना अस्पष्टता को हटा देता है। प्रस्ताव, एक अनिवार्य कीवर्ड उसके शरीर से पाश के नियंत्रण भाग को अलग करने जोड़कर अस्पष्टता को दूर करने पर विचार किया गया यानी
// The syntax of rejected proposal
for doubled in numbers.map { $0 * 2 } do {
print(doubled) // ^^
}
एक अतिरिक्त do
कीवर्ड को जोड़ने बाईं ओर स्थित "देता" ब्लॉक, यदि कोई हो, के लिए अभिव्यक्ति, और दाईं ओर ब्लॉक को लूप स्टेटमेंट के शरीर को बनाता है। इस दृष्टिकोण में एक बड़ी कमी है, क्योंकि यह एक तोड़ने वाला बदलाव है। यही कारण है कि इस प्रस्ताव को खारिज कर दिया गया है।
यह एक सुंदर चाल है। –