3-तरफ़ा बुलियन तुलना के लिए अधिकांश मुख्यधारा की भाषाएँ "x <y <z" सिंटैक्स का समर्थन क्यों नहीं करती हैं?


34

यदि मैं दो संख्याओं (या अन्य सुव्यवस्थित संस्थाओं) की तुलना करना चाहता हूं, तो मैं ऐसा करूंगा x < y। अगर मैं उनमें से तीन की तुलना करना चाहता हूं, तो हाई-स्कूल के बीजगणित के छात्र कोशिश करेंगे x < y < z। मुझ में प्रोग्रामर तो "नहीं, यह मान्य नहीं है, आपको करना होगा" के साथ जवाब देंगे x < y && y < z

अधिकांश भाषाएं जो आई हैं, वे इस वाक्य रचना का समर्थन नहीं करती हैं, जो अजीब है कि यह गणित में कितना सामान्य है। पायथन एक उल्लेखनीय अपवाद है। जावास्क्रिप्ट एक अपवाद की तरह दिखता है, लेकिन यह वास्तव में ऑपरेटर पूर्वता और निहितार्थ रूपांतरणों का एक दुर्भाग्यपूर्ण उत्पाद है; in.js, का 1 < 3 < 2मूल्यांकन करता है true, क्योंकि यह वास्तव में है (1 < 3) < 2 === true < 2 === 1 < 2

तो, मेरा सवाल यह है: आम तौर पर अपेक्षित शब्दार्थ के साथ प्रोग्रामिंग भाषाओं में क्यों x < y < zउपलब्ध नहीं है?


1
यहां व्याकरण फ़ाइल है, जिसे वे सीधे पायथन प्रलेखन में छड़ी करते हैं - मुझे नहीं लगता कि यह मुश्किल है: docs.python.org/reference/grammar.html
हारून हॉल

मैं अन्य भाषाओं को नहीं जानता, साथ ही मैं पायथन को जानता हूं, लेकिन मैं पायथन की व्याख्या की सादगी से बात कर सकता हूं। शायद मुझे जवाब देना चाहिए। लेकिन मैं इसके नुकसान के बारे में gnasher729 के निष्कर्ष से असहमत हूं।
आरोन हॉल

@ एरिकईडट - मांग गणितीय अभिव्यक्तियों को लिखने में सक्षम हो रही है जिस तरह से हमें हाई स्कूल (या पहले) में पढ़ाया गया था। हर कोई जो गणितीय रूप से झुका हुआ है वह जानता है कि $ a <b <c <d $ साधन क्या है। सिर्फ इसलिए कि एक सुविधा मौजूद है इसका मतलब यह नहीं है कि आपको इसका उपयोग करना है। जो लोग इसे पसंद नहीं करते हैं, वे हमेशा इसके उपयोग पर प्रतिबंध लगाने के लिए एक व्यक्तिगत या परियोजना नियम बना सकते हैं।
डेविड हैमेन

2
मुझे लगता है कि यह नीचे आता है कि यह LINQ का पता लगाने के लिए C # टीम (उदाहरण के रूप में) के लिए बेहतर है और भविष्य में शायद रिकॉर्ड प्रकार और पैटर्न की तुलना में कुछ सिंथेटिक चीनी जोड़ने के लिए है जो लोगों को 4 कीस्ट्रोक्स से बचाएगा और वास्तव में नहीं किसी भी अभिव्यंजकता को जोड़ें (आप हेल्परमेथोड्स भी लिख सकते हैं जैसे static bool IsInRange<T>(this T candidate, T lower, T upper) where T : IComparable<T>कि यह वास्तव में आपको देखने के लिए परेशान करता है &&)
सारा

1
एसक्यूएल काफी "मुख्यधारा" है और आप "एक्स 1 और 10 के बीच" लिख सकते हैं
जोएलफैन

जवाबों:


30

ये बाइनरी ऑपरेटर हैं, जो जब जंजीर होते हैं, तो सामान्य रूप से और स्वाभाविक रूप से एक सार सिंटैक्स ट्री का उत्पादन होता है:

बाइनरी ऑपरेटरों के लिए सामान्य सार वाक्यविन्यास पेड़

जब मूल्यांकन किया जाता है (जो आप पत्तियों से करते हैं), इससे एक बूलियन परिणाम उत्पन्न होता है x < y, तो आपको एक प्रकार की त्रुटि होती है जो करने की कोशिश कर रहा है boolean < zx < y < zजैसा कि आपने चर्चा की है, काम करने के लिए , आपको संकलक में एक विशेष मामला बनाना होगा जैसे कि एक सिंटैक्स ट्री का उत्पादन करने के लिए:

विशेष मामला वाक्यविन्यास पेड़

ऐसा नहीं है कि ऐसा करना संभव नहीं है। यह स्पष्ट रूप से है, लेकिन यह एक मामले के लिए पार्सर में कुछ जटिलता जोड़ता है जो वास्तव में अक्सर सामने नहीं आता है। आप मूल रूप से एक प्रतीक बना रहे हैं जो कभी-कभी द्विआधारी ऑपरेटर की तरह काम करता है और कभी-कभी प्रभावी रूप से एक टर्नरी ऑपरेटर की तरह काम करता है, जिसमें त्रुटि से निपटने के सभी निहितार्थ होते हैं और ऐसा होता है। यह चीजों को गलत होने के लिए बहुत अधिक जगह जोड़ता है कि भाषा डिजाइनर यदि संभव हो तो इससे बचेंगे।


1
"तब आपको बूलियन <z" करने की कोशिश करने में एक प्रकार की त्रुटि मिलती है - यदि कंपाइलर z तुलना के लिए y-in-place का मूल्यांकन करके अनुमति नहीं देता है। "यह चीजों को गलत होने के लिए बहुत अधिक जगह जोड़ता है कि भाषा डिजाइनर संभव नहीं तो बचेंगे।" वास्तव में, पायथन को ऐसा करने में कोई समस्या नहीं है, और पार्स करने का तर्क किसी एकल फ़ंक्शन तक ही सीमित है: hg.python.org/cpython/file/tip/Python/ast.c#l1122 - चीजों के जाने के लिए बहुत अधिक जगह नहीं है। गलत। "कभी-कभी एक बाइनरी ऑपरेटर की तरह काम करता है और कभी-कभी प्रभावी रूप से एक ट्रिनरी ऑपरेटर की तरह काम करता है," पायथन में, पूरी तुलना श्रृंखला टर्नरी है।
हारून हॉल

2
मैंने कभी नहीं कहा कि यह उल्लेखनीय नहीं था, बस अतिरिक्त जटिलता के साथ अतिरिक्त काम। अन्य भाषाओं को अपने तुलना ऑपरेटरों को संभालने के लिए कोई अलग कोड नहीं लिखना होता है । आप इसे अन्य बाइनरी ऑपरेटरों के साथ मुफ्त में प्राप्त करते हैं। आपको बस उनकी पूर्वता बताना होगा।
कार्ल बेवेलफेल्ट

हां, लेकिन ... बहुत सारी भाषाओं में पहले से ही टर्नरी ऑपरेटर उपलब्ध है?
जेन्सजी

1
@ जेन्सजी टर्नरी के अर्थ का अर्थ है कि इसमें 3 तर्क हैं। आपके लिंक के संदर्भ में, यह एक टर्नरी स्थिति ऑपरेटर है। जाहिरा तौर पर "त्रिशूल" शब्द एक ऑपरेटर के लिए गढ़ा गया है जो 2 लेता है, लेकिन वास्तव में 3 लेता है। इस उत्तर के साथ मेरा प्राथमिक मुद्दा यह है कि यह ज्यादातर FUD है।
एरोन हॉल

2
मैं इस स्वीकृत जवाब पर उतरने वालों में से एक हूं। (@JesseTG:। इस उत्तर unaccept कृपया) इस सवाल भ्रमित क्या x<y<zमतलब है, या अधिक महत्वपूर्ण बात यह x<y<=z। यह उत्तर x<y<zएक ट्रिनिटी ऑपरेटर के रूप में व्याख्या करता है। यही कारण है कि इस अच्छी तरह से परिभाषित गणितीय अभिव्यक्ति की व्याख्या नहीं की जानी चाहिए। x<y<zइसके बजाय आशुलिपि है (x<y)&&(y<z)। व्यक्तिगत तुलना अभी भी द्विआधारी है।
डेविड हैम्मन

37

x < y < zआमतौर पर प्रोग्रामिंग भाषाओं में क्यों उपलब्ध नहीं है?

इस उत्तर में मैं यह निष्कर्ष निकालता हूं

  • यद्यपि यह निर्माण भाषा के व्याकरण में लागू करने के लिए तुच्छ है और भाषा उपयोगकर्ताओं के लिए मूल्य बनाता है,
  • अधिकांश भाषाओं में मौजूद नहीं होने वाले प्राथमिक कारण अन्य विशेषताओं के सापेक्ष इसके महत्व के कारण हैं और भाषाओं के संचालन की अनिच्छा या तो निकायों के लिए
    • संभावित रूप से टूटने वाले परिवर्तनों से परेशान उपयोगकर्ता
    • सुविधा को लागू करने के लिए कदम (यानी: आलस्य)।

परिचय

मैं इस सवाल पर एक पायथनवादी दृष्टिकोण से बोल सकता हूं। मैं इस सुविधा के साथ एक भाषा का उपयोगकर्ता हूं और मुझे भाषा के कार्यान्वयन विवरण का अध्ययन करना पसंद है। इसके अलावा, मैं C और C ++ जैसी भाषाओं को बदलने की प्रक्रिया से कुछ हद तक परिचित हूं (आईएसओ मानक समिति द्वारा शासित है और वर्ष तक इसका संस्करण है।) और मैंने रूबी और पायथन दोनों पर ब्रेकिंग परिवर्तन लागू किए हैं।

पायथन के प्रलेखन और कार्यान्वयन

डॉक्स / व्याकरण से, हम देखते हैं कि हम तुलना ऑपरेटरों के साथ किसी भी संख्या के भावों की श्रृंखला बना सकते हैं:

comparison    ::=  or_expr ( comp_operator or_expr )*
comp_operator ::=  "<" | ">" | "==" | ">=" | "<=" | "!="
                   | "is" ["not"] | ["not"] "in"

और प्रलेखन आगे बताता है:

तुलनाएँ मनमाने ढंग से की जा सकती हैं, उदाहरण के लिए, x <y <= z, x <y और y <= z के बराबर है, सिवाय इसके कि y का मूल्यांकन केवल एक बार किया जाता है (लेकिन दोनों मामलों में z का मूल्यांकन तब नहीं किया जाता है जब x <y पाया जाता है झूठा होना)।

तार्किक साम्य

इसलिए

result = (x < y <= z)

तार्किक है बराबर के मूल्यांकन के संदर्भ में x, yहै, और z, एक अपवाद के रूप yमें दो बार मूल्यांकन किया जाता है:

x_lessthan_y = (x < y)
if x_lessthan_y:       # z is evaluated contingent on x < y being True
    y_lessthan_z = (y <= z)
    result = y_lessthan_z
else:
    result = x_lessthan_y

फिर, अंतर यह है कि y का मूल्यांकन केवल एक समय के साथ किया जाता है (x < y <= z)

(ध्यान दें, कोष्ठक पूरी तरह से अनावश्यक और निरर्थक हैं, लेकिन मैंने उन्हें अन्य भाषाओं से आने वाले लोगों के लाभ के लिए उपयोग किया है, और उपरोक्त कोड काफी कानूनी पायथन है।)

पार्स किए गए सार सिंटेक्स ट्री का निरीक्षण

हम निरीक्षण कर सकते हैं कि पायथन ने तुलनात्मक संचालकों को कैसे प्रशिक्षित किया:

>>> import ast
>>> node_obj = ast.parse('"foo" < "bar" <= "baz"')
>>> ast.dump(node_obj)
"Module(body=[Expr(value=Compare(left=Str(s='foo'), ops=[Lt(), LtE()],
 comparators=[Str(s='bar'), Str(s='baz')]))])"

इसलिए हम देख सकते हैं कि यह वास्तव में पाइथन या किसी अन्य भाषा को पार्स करने के लिए मुश्किल नहीं है।

>>> ast.dump(node_obj, annotate_fields=False)
"Module([Expr(Compare(Str('foo'), [Lt(), LtE()], [Str('bar'), Str('baz')]))])"
>>> ast.dump(ast.parse("'foo' < 'bar' <= 'baz' >= 'quux'"), annotate_fields=False)
"Module([Expr(Compare(Str('foo'), [Lt(), LtE(), GtE()], [Str('bar'), Str('baz'), Str('quux')]))])"

और वर्तमान में स्वीकार किए गए उत्तर के विपरीत, टर्नरी ऑपरेशन एक जेनेरिक तुलना ऑपरेशन है, जो पहली अभिव्यक्ति लेता है, विशिष्ट तुलनाओं का एक पुनरावृत्ति और आवश्यक के रूप में मूल्यांकन करने के लिए अभिव्यक्ति नोड्स का एक चलने योग्य है। सरल।

पाइथन पर निष्कर्ष

मैं व्यक्तिगत रूप से रेंज शब्दार्थ को काफी सुरुचिपूर्ण मानता हूं, और मुझे पता है कि अधिकांश पायथन पेशेवर इस सुविधा का उपयोग करने के लिए इसे नुकसान पहुंचाने पर विचार करने के बजाय प्रोत्साहित करेंगे - शब्दार्थ अच्छी तरह से प्रतिष्ठित प्रलेखन में स्पष्ट रूप से कहा गया है (जैसा कि ऊपर उल्लेख किया गया है)।

ध्यान दें कि कोड लिखा होने की तुलना में बहुत अधिक पढ़ा जाता है। कोड की पठनीयता में सुधार करने वाले परिवर्तनों को गले लगाया जाना चाहिए, न कि भय, अनिश्चितता और संदेह के सामान्य दर्शकों को बढ़ाकर ।

तो प्रोग्रामिंग भाषाओं में x <y <z आमतौर पर उपलब्ध क्यों नहीं है?

मुझे लगता है कि ऐसे कारणों का संगम है जो फ़ीचर के सापेक्ष महत्व और भाषाओं के राज्यपालों द्वारा अनुमत परिवर्तन की सापेक्ष गति / जड़ता के आसपास केंद्र हैं।

अन्य महत्वपूर्ण भाषा सुविधाओं के बारे में भी इसी तरह के प्रश्न पूछे जा सकते हैं

जावा या C # में एकाधिक वंशानुक्रम उपलब्ध क्यों नहीं है? प्रश्न के लिए यहाँ कोई अच्छा जवाब नहीं है । शायद डेवलपर्स बहुत आलसी थे, जैसा कि बॉब मार्टिन ने आरोप लगाया है, और दिए गए कारण केवल बहाने हैं। और कई विरासत कंप्यूटर विज्ञान में एक बहुत बड़ा विषय है। यह निश्चित रूप से ऑपरेटर की तुलना में अधिक महत्वपूर्ण है।

साधारण वर्कअराउंड मौजूद हैं

तुलना करने वाला ऑपरेटर शाइनिंग सुरुचिपूर्ण है, लेकिन किसी भी तरह से कई उत्तराधिकार के रूप में महत्वपूर्ण नहीं है। और जैसे जावा और C # में वर्कअराउंड के रूप में इंटरफेस है, वैसे ही हर भाषा कई तुलनाओं के लिए है - आप बस बूलियन और "s के साथ तुलना की श्रृंखला बनाते हैं, जो आसानी से पर्याप्त काम करता है।

अधिकांश भाषाएं समिति द्वारा शासित होती हैं

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

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

यदि कोई भाषा x < y < zअपेक्षित गणितीय शब्दार्थ के बिना अनुमति देती है , तो यह एक ब्रेकिंग परिवर्तन होगा। यदि यह पहली जगह में इसकी अनुमति नहीं देता है, तो इसे जोड़ना लगभग तुच्छ होगा।

ब्रेकिंग परिवर्तन

ब्रेकिंग परिवर्तन वाली भाषाओं के बारे में: हम अपडेट भाषाओं को ब्रेकिंग व्यवहार परिवर्तनों के साथ करते हैं - लेकिन उपयोगकर्ता ऐसा नहीं करते हैं, विशेष रूप से उन सुविधाओं के उपयोगकर्ता जो टूट गए हैं। यदि कोई उपयोगकर्ता के पूर्व व्यवहार पर भरोसा कर रहा है x < y < z, तो वे संभवतः जोर से विरोध करेंगे। और चूंकि अधिकांश भाषाएं समिति द्वारा शासित होती हैं, मुझे संदेह है कि हम इस तरह के बदलाव का समर्थन करने के लिए बहुत अधिक राजनीतिक इच्छाशक्ति प्राप्त करेंगे।


ईमानदारी से, मैं भाषाओं द्वारा प्रदान किए जाने वाले शब्दार्थ के साथ कोई समस्या नहीं लेता हूं जो कि श्रृंखला तुलना संचालन जैसे कि `x <y <z` है, लेकिन यह एक डेवलपर के लिए मानसिक रूप से मानचित्र के x < y < zलिए तुच्छ है (x < y) && (y < z)। निट्स चुनना, जंजीर तुलना के लिए मानसिक मॉडल सामान्य गणित है। क्लासिक तुलना सामान्य रूप से गणित नहीं है, लेकिन बूलियन तर्क है। x < yएक द्विआधारी उत्तर पैदा करता है {0}y < zएक द्विआधारी उत्तर पैदा करता है {1}{0} && {1}वर्णनात्मक उत्तर पैदा करता है। तर्क की रचना होती है, न कि जंजीर से।
। एलन बेट्स

बेहतर संवाद करने के लिए, मैंने एक एकल वाक्य के साथ उत्तर दिया है जो सीधे संपूर्ण सामग्री को संक्षेप में प्रस्तुत करता है। यह एक लंबा वाक्य है, इसलिए मैंने इसे गोलियों में तोड़ दिया।
आरोन हॉल

2
इस सुविधा को लागू करने की प्रमुख वजह यह है कि गुइडो से पहले किसी ने भी इसके बारे में नहीं सोचा था। सी से विरासत में मिली भाषाओं को यह "सही" (गणितीय रूप से सही) अब मुख्य रूप से नहीं मिल सकता है क्योंकि सी के डेवलपर्स ने इसे 40 साल पहले "गलत" (गणितीय रूप से गलत) पाया था। वहाँ बहुत सारे कोड हैं जो उन भाषाओं की व्याख्या करने के प्रतिरूपात्मक प्रकृति पर निर्भर करते हैं x<y<z। एक भाषा के पास एक बार इस तरह का अधिकार प्राप्त करने का मौका होता है, और एक मौका भाषा की शुरुआत में होता है।
डेविड हैमेन 18

1
@ K.AlanBates आप 2 अंक बनाते हैं: 1) ऑपरेटर चेनिंग ढलानदार है और 2) कि वाक्यगत चीनी का कोई मूल्य नहीं है। पहली बार: मैंने प्रदर्शित किया है कि ऑपरेटर का शत-प्रतिशत निर्धारण 100% है, क्या मैंने नहीं किया है? शायद कुछ प्रोग्रामर निर्माण को समझने के लिए अपनी क्षमता का विस्तार करने के लिए मानसिक रूप से आलसी हैं? दूसरे बिंदु तक: यह मुझे लगता है जैसे आप सीधे पठनीयता के खिलाफ बहस कर रहे हैं? जब यह पठनीयता में सुधार करता है, तो आमतौर पर सिंटैक्टिक शुगर को अच्छी बात नहीं माना जाता है? अगर इस तरह से सोचना सामान्य है, तो कोई प्रोग्रामर इस तरह से संवाद क्यों नहीं करना चाहेगा? कोड को पढ़ने के लिए लिखा जाना चाहिए, नहीं?
आरोन हॉल

2
I have watched both Ruby and Python implement breaking changes.जो लोग उत्सुक हैं, यहां लूप वेरिएबल्स और क्लोजर को शामिल करते हुए C # 5.0 में एक ब्रेकिंग परिवर्तन है: blogs.msdn.microsoft.com/ericlippert/2009/11/12/…
user2023861

13

कंप्यूटर की भाषाएं सबसे छोटी संभव इकाइयों को परिभाषित करने की कोशिश करती हैं और आपको उन्हें जोड़ती हैं। सबसे छोटी संभव इकाई "x <y" की तरह कुछ होगी जो बूलियन परिणाम देती है।

आप एक टर्नरी ऑपरेटर के लिए पूछ सकते हैं। एक उदाहरण x <y <z होगा। अब हम ऑपरेटरों के किस संयोजन की अनुमति देते हैं? स्पष्ट रूप से x> y> z या x> = y> = z या x> y> = z या शायद x == y == z की अनुमति दी जानी चाहिए। X <y> z के बारे में क्या? x! = y! = z पिछले एक का क्या मतलब है, x! = Y और y! = Z या कि तीनों अलग-अलग हैं?

अब तर्क प्रचार: C या C ++ में, तर्क को एक सामान्य प्रकार में बढ़ावा दिया जाएगा। तो क्या x <y <z x का मतलब डबल है लेकिन y और z लंबे लंबे int हैं? तीनों ने डबल का प्रचार किया? या y को एक बार डबल के रूप में लिया जाता है और दूसरी बार लंबे समय तक int के रूप में? यदि C ++ एक या दोनों ऑपरेटरों के ओवरलोड होने पर क्या होता है?

और अंतिम, क्या आप किसी भी संख्या में ऑपरेंड की अनुमति देते हैं? जैसे <b> c <d> e <f> g?

खैर, यह सब बहुत जटिल हो जाता है। अब जो मैं बुरा नहीं मानूंगा वह x <y <z सिंटैक्स त्रुटि पैदा करता है। क्योंकि शुरुआती लोगों को हुए नुकसान की तुलना में इसकी उपयोगिता बहुत कम है, जो यह पता नहीं लगा सकते हैं कि x <y <z वास्तव में क्या करता है।


4
तो, संक्षेप में, यह अच्छी तरह से डिजाइन करने के लिए सिर्फ एक कठिन विशेषता है।
जॉन पूर्डी

2
यह वास्तव में यह समझाने का कारण नहीं है कि कोई भी अच्छी तरह से जानने वाली भाषा में यह विशेषता क्यों नहीं है। तथ्य की बात के रूप में, इसे भाषा में अच्छी तरह से परिभाषित तरीके से शामिल करना बहुत आसान है। यह सिर्फ देखने की बात है कि प्रत्येक ऑपरेटर के बाइनरी के बजाय समान प्रकार के ऑपरेटरों द्वारा जुड़ी सूची के रूप में। एक ही राशि के लिए किया जा सकता है x + y + z, एकमात्र अंतर के साथ जो किसी भी शब्दार्थिक अंतर को नहीं दर्शाता है। तो यह सिर्फ इतना है कि कोई अच्छी तरह से ज्ञात भाषा कभी भी ऐसा करने की परवाह नहीं करती है।
सेमीस्टर

1
मुझे लगता है कि पायथन में यह एक अनुकूलन का एक सा है, ( केवल एक बार का मूल्यांकन किया x < y < zजा रहा है , ((x < y) and (y < z))लेकिन जो मैं संकलित भाषाओं के आसपास अपने तरीके से अनुकूलन की कल्पना करता हूं)। "क्योंकि शुरुआती लोगों को हुए नुकसान की तुलना में इसकी उपयोगिता बहुत कम है, जो यह पता नहीं लगा सकते हैं कि x <y <z वास्तव में क्या करता है।" मुझे लगता है कि यह अविश्वसनीय रूप से उपयोगी है। शायद उसके लिए -1 है ...y
एरॉन हॉल

यदि किसी का लक्ष्य एक ऐसी भाषा डिजाइन करना है जो उन सभी चीजों को समाप्त कर देती है जो प्रोग्रामर के सबसे मूर्ख के लिए भ्रामक हो सकती हैं, तो ऐसी भाषा पहले से मौजूद है: COBOL। मैं बल्कि अजगर का उपयोग करूँगा, अपने आप को, जहाँ कोई वास्तव a < b > c < d > e < f > gमें "स्पष्ट" अर्थ के साथ लिख सकता है (a < b) and (b > c) and (c < d) and (d > e) and (e < f) and (f > g)। सिर्फ इसलिए कि आप लिख सकते हैं कि इसका मतलब आपको नहीं होना चाहिए। इस तरह की संकीर्णताओं को खत्म करना कोड समीक्षा का उद्देश्य है। दूसरी ओर, 0 < x < 8अजगर में लिखने से स्पष्ट (कोई डरा हुआ उद्धरण नहीं है) जिसका अर्थ है कि एक्स 0 और 8 के बीच स्थित है, विशेष।
डेविड हैमेन

@DavidHammen, विडंबना यह कोबोल वास्तव में एक <b <ग की अनुमति नहीं है
JoelFan

10

कई प्रोग्रामिंग भाषाओं में, x < yएक द्विआधारी अभिव्यक्ति है जो दो ऑपरेंड को स्वीकार करता है और एक एकल बूलियन परिणाम का मूल्यांकन करता है इसलिए, यदि कई अभिव्यक्तियों का पीछा करते हुए, true < zऔर false < zइसका कोई मतलब नहीं होगा, और यदि वे अभिव्यक्ति सफलतापूर्वक मूल्यांकन करते हैं, तो वे गलत परिणाम उत्पन्न करने की संभावना रखते हैं।

यह x < yएक फ़ंक्शन कॉल के रूप में सोचना बहुत आसान है जो दो मापदंडों को लेता है और एक एकल बूलियन परिणाम पैदा करता है। वास्तव में, यह है कि कितनी भाषाएं इसे हुड के तहत लागू करती हैं। यह आसानी से संकलन योग्य है, और यह सिर्फ काम करता है।

x < y < zपरिदृश्य और अधिक जटिल है। अब संकलक, प्रभाव में, फैशन के लिए है तीन कार्य: x < y, y < z, और उन दो मूल्यों का परिणाम है, एक साथ anded सब एक यकीनन के संदर्भ में अस्पष्ट भाषा व्याकरण

उन्होंने इसे दूसरे तरीके से क्यों किया? क्योंकि यह अस्पष्ट व्याकरण है, लागू करने के लिए बहुत आसान है, और सही होने के लिए बहुत आसान है।


2
यदि आप भाषा डिजाइन कर रहे हैं, तो आपके पास इसे सही परिणाम देने का अवसर है ।
JesseTG

2
बेशक यह सवाल का जवाब देता है। यदि प्रश्न वास्तव में ऐसा है , तो इसका उत्तर "क्योंकि यही भाषा डिजाइनरों ने चुना है।" यदि आप इससे बेहतर उत्तर दे सकते हैं, तो इसके लिए जाएं। ध्यान दें कि Gnasher ने अनिवार्य रूप से अपने उत्तर के पहले पैराग्राफ में ठीक यही बात कही है ।
रॉबर्ट हार्वे

3
फिर, आप बालों को विभाजित कर रहे हैं। प्रोग्रामर ऐसा करते हैं। "क्या आप कचरा बाहर निकालना चाहते हैं?" "नहीं।" "क्या आप कचरा बाहर निकालेंगे?" "हाँ।"
रॉबर्ट हार्वे

2
मैं आखिरी पैराग्राफ भी लड़ता हूं। पायथन जंजीरों की तुलना का समर्थन करता है, और इसका पार्सर एलएल (1) है। यह आवश्यक नहीं है कि या तो शब्दार्थ को परिभाषित करना और उसे लागू करना कठिन है: पायथन सिर्फ इतना कहता है कि e1 op1 e2 op2 e3 op3 ...इसके बराबर है e1 op e2 and e2 op2 e3 and ...कि प्रत्येक अभिव्यक्ति का केवल एक बार मूल्यांकन किया जाता है। (BTW इस सरल नियम का भ्रामक साइड इफेक्ट है कि बयानों का a == b is Trueअब कोई इच्छित प्रभाव नहीं है।)

2
@RobertHarvey re:answerयह वह जगह थी जहाँ मेरा मन तुरंत मुख्य प्रश्न पर मेरी टिप्पणी के लिए गया। मैं x < y < zभाषा के शब्दार्थों के लिए कोई विशिष्ट मूल्य जोड़ने के लिए समर्थन पर विचार नहीं करता। (x < y) && (y < z)अधिक व्यापक रूप से समर्थित है, अधिक अन्वेषण, अधिक अभिव्यंजक है, अधिक आसानी से अपने घटकों में पच जाता है, अधिक संयोजी, अधिक तार्किक, अधिक आसानी से परिलक्षित होता है।
। एलन बेट्स

6

अधिकांश मुख्यधारा की भाषाएँ (कम से कम आंशिक रूप से) वस्तु-उन्मुख हैं। मौलिक रूप से, OO का अंतर्निहित सिद्धांत यह है कि वस्तुएं अन्य वस्तुओं (या स्वयं) को संदेश भेजती हैं, और उस संदेश के रिसीवर का उस संदेश पर प्रतिक्रिया करने का पूरा नियंत्रण होता है।

अब, आइए देखें कि हम कैसे कुछ लागू करेंगे

a < b < c

हम इसका सख्ती से बाएं से दाएं (बाएं-सहयोगी) मूल्यांकन कर सकते हैं:

a.__lt__(b).__lt__(c)

लेकिन अब हम __lt__परिणाम पर कॉल करते हैं a.__lt__(b), जो कि ए Boolean। इसका कोई अर्थ नही बन रहा है।

आइए, सही-सहयोगी की कोशिश करें:

a.__lt__(b.__lt__(c))

नहीं, यह भी मतलब नहीं है। अब, हमारे पास है a < (something that's a Boolean)

ठीक है, इसे सिंटैक्टिक शुगर के रूप में इलाज करने के बारे में क्या। चलो n <तुलनाओं की एक श्रृंखला बनाते हैं एक n-1-ary संदेश भेजें। यानी हो सकता है, हम संदेश भेजने __lt__के लिए a, गुजर bऔर cतर्कों के रूप:

a.__lt__(b, c)

ठीक है, यह काम करता है, लेकिन यहां एक अजीब विषमता है: aयह तय करने के लिए मिलता है कि क्या यह कम है b। लेकिन bयह तय करने के लिए नहीं है कि क्या यह कम है c, बजाय इसके कि निर्णय भी किया जाता है a

एन-एरी संदेश के रूप में इसे व्याख्या करने के बारे में क्या भेजें this?

this.__lt__(a, b, c)

आखिरकार! यह काम कर सकता है। हालांकि, इसका मतलब यह है कि वस्तुओं का आदेश अब वस्तु की संपत्ति नहीं है (जैसे कि न aतो कम bहै और न aही संपत्ति का है b) बल्कि संदर्भ की संपत्ति (यानी this) है।

एक मुख्यधारा के दृष्टिकोण से जो अजीब लगता है। हालाँकि, जैसे हास्केल, यह सामान्य है। Ordउदाहरण के लिए, टाइपकास्ट के कई अलग-अलग कार्यान्वयन हो सकते हैं , और aइससे कम या नहीं b, इस बात पर निर्भर करता है कि टाइपकाॅल का उदाहरण किस दायरे में है।

लेकिन वास्तव में, यह बिल्कुल अजीब नहीं है ! दोनों जावा ( Comparator) और .NET ( IComparer) में इंटरफेस हैं जो आपको अपने खुद के ऑर्डरिंग रिलेशन को इंजेक्ट करने की अनुमति देते हैं। इस प्रकार, वे पूरी तरह से स्वीकार करते हैं कि एक ऑर्डरिंग एक ऐसी चीज नहीं है जो एक प्रकार के लिए तय की गई है, बल्कि इसके संदर्भ पर निर्भर करती है।

जहाँ तक मुझे पता है, वर्तमान में ऐसी कोई भाषा नहीं है जो ऐसा अनुवाद करती हो। एक मिसाल है, हालांकि: इओक और सेप दोनों के पास अपने डिजाइनर को "ट्रिनरी ऑपरेटर्स" कहते हैं - ऑपरेटर जो सिंटैक्टिक रूप से द्विआधारी हैं, लेकिन शब्दार्थ टर्नरी हैं। विशेष रूप से,

a = b

है संदेश भेजने के रूप में व्याख्या =करने के लिए aगुजर bसंदेश भेजने तर्क के रूप में, बल्कि के रूप में ="वर्तमान ग्राउंड" (एक अवधारणा समान है, लेकिन समान नहीं करने के लिए this) से गुजर रहा aहै और bतर्क के रूप में। तो, के a = bरूप में व्याख्या की है

=(a, b)

और नहीं

a =(b)

इसे आसानी से n-ary ऑपरेटरों के लिए सामान्यीकृत किया जा सकता है।

ध्यान दें कि यह वास्तव में ओओ भाषाओं के लिए अजीब है। OO में, हमारे पास हमेशा एक ही वस्तु होती है, जो अंततः एक संदेश भेजने की व्याख्या करने के लिए ज़िम्मेदार होती है, और जैसा कि हमने देखा है, यह किसी चीज़ के लिए तुरंत स्पष्ट नहीं है a < b < cकि कौन सी वस्तु होनी चाहिए।

यह प्रक्रियात्मक या कार्यात्मक भाषाओं पर लागू नहीं होता है। उदाहरण के लिए, स्कीम , कॉमन लिस्प और क्लोजर में , <फ़ंक्शन एन-एरी है, और इसे मनमाने ढंग से संख्या के साथ कहा जा सकता है।

विशेष रूप से, <करता नहीं मतलब है "कम से कम", बल्कि इन कार्यों थोड़ा अलग तरीके से व्याख्या की जाती हैं:

(<  a b c d) ; the sequence a, b, c, d is monotonically increasing
(>  a b c d) ; the sequence a, b, c, d is monotonically decreasing
(<= a b c d) ; the sequence a, b, c, d is monotonically non-decreasing
(>= a b c d) ; the sequence a, b, c, d is monotonically non-increasing

3

यह सिर्फ इसलिए है क्योंकि भाषा डिजाइनरों ने इसके बारे में नहीं सोचा था या नहीं लगता कि यह एक अच्छा विचार था। अजगर ऐसा करता है जैसा कि आपने एक सरल (लगभग) एलएल (1) व्याकरण के साथ वर्णित किया है।


1
यह अभी भी किसी भी मुख्यधारा की भाषा में एक सामान्य व्याकरण के साथ पार्स करेगा; यह सिर्फ @RobertHarvey कारण के लिए सही ढंग से समझा नहीं जाएगा।
मेसन व्हीलर

@MasonWheeler नहीं, जरूरी नहीं। यदि नियम लिखे गए हैं ताकि तुलना अन्य संचालकों के साथ विनिमेय हो (कहते हैं, क्योंकि उनकी एक ही मिसाल है), तो आपको सही व्यवहार नहीं मिलेगा। तथ्य यह है कि पायथन सभी तुलनाओं को एक स्तर पर रख रहा है, जो इसे अनुक्रम के संयोजन के रूप में व्यवहार करने की अनुमति देता है।
नील जी

1
ज़रुरी नहीं। 1 < 2 < 3जावा या C # में डालें और आपको ऑपरेटर पूर्वता के साथ कोई समस्या नहीं है; आपको अमान्य प्रकारों की समस्या है। मुद्दा यह है कि यह अभी भी ठीक वैसा ही होगा जैसा कि आपने इसे लिखा था, लेकिन आपको कंपाइलर में विशेष-केस लॉजिक की आवश्यकता होती है ताकि इसे व्यक्तिगत तुलनाओं के अनुक्रम से जंजीरों की तुलना में बदल दिया जा सके।
मेसन व्हीलर

2
@MasonWheeler मैं जो कह रहा हूं वह यह है कि काम करने के लिए भाषा को डिजाइन करना होगा। इसका एक हिस्सा व्याकरण का अधिकार प्राप्त कर रहा है। (यदि नियम लिखे गए हैं, ताकि तुलना अन्य संचालकों के साथ विनिमेय हो, तो कहें, क्योंकि उनकी एक ही प्राथमिकता है, तो आपको सही व्यवहार नहीं मिलेगा।) इसका एक और हिस्सा एएसटी को एक संयोजन के रूप में व्याख्या कर रहा है, जो ++ है। नहीं करता है मेरे जवाब का मुख्य बिंदु यह है कि यह एक भाषा डिजाइनर का निर्णय है।
नील जी

@MasonWheeler मुझे लगता है कि हम सहमत हैं। मैं सिर्फ इस बात पर प्रकाश डाल रहा था कि इसके लिए व्याकरण को सही करना कठिन नहीं है। यह केवल पहले से तय करने की बात है कि आप इसे इस तरह से काम करना चाहते हैं।
नील जी

2

निम्न C ++ प्रोग्राम संकलित करने के लिए क्लैंग से एक पीरी के साथ संकलित करता है, यहां तक ​​कि उच्चतम संभव स्तर ( -Weverything) के लिए निर्धारित चेतावनियों के साथ :

#include <iostream>
int main () { std::cout << (1 < 3 < 2) << '\n'; }

दूसरी ओर गन्न संकलक सूट मुझे अच्छी तरह से चेतावनी देता है कि comparisons like 'X<=Y<=Z' do not have their mathematical meaning [-Wparentheses]

तो, मेरा सवाल यह है: क्यों एक्स <y <z आमतौर पर प्रोग्रामिंग भाषाओं में उपलब्ध नहीं है, अपेक्षित शब्दार्थ के साथ?

इसका उत्तर सरल है: पश्चगामी संगतता। जंगली में कोड की एक बड़ी मात्रा है जो बराबर का उपयोग करती है 1<3<2और परिणाम को सच-ईश होने की उम्मीद करती है।

एक भाषा डिजाइनर के पास यह "सही" होने का एक मौका होता है, और यही वह समय होता है जब भाषा को पहली बार डिजाइन किया जाता है। प्रारंभ में इसे "गलत" करें इसका मतलब है कि अन्य प्रोग्रामर जल्दी से उस "गलत" व्यवहार का लाभ उठाएंगे। इसे दूसरी बार "सही" करने से मौजूदा कोड आधार टूट जाएगा।


+1 क्योंकि यह प्रोग्राम एक अभिव्यक्ति के परिणाम के रूप में '1' को उत्पन्न करता है जो स्पष्ट रूप से गणित में गलत है। यद्यपि यह वंचित है, अतुलनीय चर नामों के साथ एक वास्तविक दुनिया उदाहरण यदि यह भाषा सुविधा जोड़ी गई थी, तो यह डीबगिंग दुःस्वप्न बन जाएगी।
सेठ बट्टिन

@SethBattin - यह पायथन में डिबगिंग दुःस्वप्न नहीं है। पायथन में एकमात्र समस्या है if x == y is True : ..., मेरी राय: जो लोग उस तरह का कोड लिखते हैं, वे कुछ अतिरिक्त-विशेष, असाधारण प्रकार की यातना के अधीन होते हैं, जो (यदि वह अभी जीवित था) तो टॉर्केमाडा को खुद को बेहोश कर देगा।
डेविड हैमेन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.