2010-06-06 18 views
7

जब a अपरिभाषित है, तो a || 1 एक त्रुटि फेंक देगा, लेकिन a = a || 1 नहीं होगा। क्या यह थोड़ा असंगत नहीं है?रुबी में क्यों, एक || 1 'ए' अनिर्धारित होने पर एक त्रुटि फेंक देगा, लेकिन एक = ए || 1 नहीं होगा?

irb(main):001:0> a 
NameError: undefined local variable or method 'a' for main:Object 
     from (irb):1 
     from c:/ruby/bin/irb:12:in '<main>' 

irb(main):002:0> a || 1 
NameError: undefined local variable or method 'a' for main:Object 
     from (irb):2 
     from c:/ruby/bin/irb:12:in '<main>' 

irb(main):003:0> a = a || 1 
=> 1 
+0

http://stackoverflow.com/questions/1462407/ruby-edge-cases का डुप्लिकेट –

उत्तर

9
a 

यहां, आप a का मूल्यांकन कर रहे हैं, जिसे परिभाषित नहीं किया गया है। इसलिए, आपको अपवाद मिलता है।

a || 1 

यहाँ, आप अभी भीa मूल्यांकन करने के लिए बूलियन अभिव्यक्ति का मूल्य निर्धारित करने के लिए है। ऊपर की तरह, a परिभाषित नहीं किया गया है। इसलिए, आपको अपवाद मिलता है।

a = a || 1 

यहाँ, a परिभाषित किया गया है। इसे एक अनियमित स्थानीय चर माना जाता है। रूबी में, अप्रारंभीकृत चर nil का मूल्यांकन, इसलिए काम अभिव्यक्ति की दाहिने हाथ की ओर nil || 1 जो 1 का मूल्यांकन करने के लिए मूल्यांकन करता है, इसलिए काम अभिव्यक्ति की वापसी मान 1 है और दुष्प्रभाव यह है कि a1 को आरंभ नहीं हो जाता है।

संपादित करें: ऐसा लगता है कि जब चर को परिभाषित किया जाता है और जब वे रूबी में प्रारंभ होते हैं तो कुछ भ्रम होता है। पार्स समय पर परिभाषित किया गया है लेकिन रनटाइम पर प्रारंभ किया गया। आप इसे यहां देख सकते हैं:

foo # => NameError: undefined local variable or method `foo' for main:Object 

foo अपरिभाषित है।

if false 
    foo = 'This will never get executed' 
end 

इस बिंदु पर, foo परिभाषित किया गया है, भले ही लाइन निष्पादित हो कभी नहीं होगा। तथ्य यह है कि रेखा कभी निष्पादित नहीं होती है, पूरी तरह से अप्रासंगिक है, क्योंकि दुभाषिया के पास इसके साथ कुछ भी करने का कोई अधिकार नहीं है: स्थानीय चर को पार्सर द्वारा परिभाषित किया जाता है, और पार्सर स्पष्ट रूप से इस रेखा को देखता है।

foo # => nil 

कोई त्रुटि है, क्योंकि foo परिभाषित किया गया है, और यह nil का आकलन करती है क्योंकि यह अप्रारंभीकृत है।

+0

+1, हालांकि मुझे लगता है कि "यह एक अनियमित स्थानीय चर के रूप में परिभाषित किया गया है।" थोड़ा उलझन में है। जब आप 'var = expr' करते हैं, तो आप' var' को परिभाषित नहीं कर रहे हैं। आप var को 'expr' के मान के रूप में परिभाषित कर रहे हैं। यह सिर्फ इतना है कि 'expr' मूल्यांकन करते समय,' var' को अनियंत्रित किया जाता है, जिसका अर्थ है कि 'expr' के अंदर' var' के किसी भी संदर्भ का मूल्यांकन शून्य होगा। – sepp2k

+1

@ sepp2k: वे दो बहुत अलग कदम हैं। परिवर्तनीय परिभाषा पार्सर, दुभाषिया में प्रारंभिकरण में होती है। रूबी कार्यान्वयन के आधार पर, दो घटनाओं के बीच एक महत्वपूर्ण समय हो सकता है। BlueRuby में, उदाहरण के लिए, रूबी स्रोत कोड को BRIL (BlueRuby इंटरमीडिएट भाषा) में पार्स किया जाता है, जो तब डेटाबेस में संग्रहीत हो जाता है, जब आप * रूबी प्रोग्राम इंस्टॉल करते हैं। यह * साल * हो सकता है जब तक कोई वास्तव में * कार्यक्रम * चलाता है। इस बार, चर परिभाषित किया गया था लेकिन प्रारंभ नहीं किया गया था। विभिन्न मशीनों पर भी दो चीजें हो सकती हैं। –

1

जब आप a || 1 करते हैं, आप a का मूल्य जो अपरिभाषित है देखने के लिए यह पूछ रहे हैं।

आप a = a || 1 करना जब आप a जो एक त्रुटि देने के लिए प्रतीत नहीं होता है करने के लिए a बताए का मूल्य देखने के लिए यह पूछ रहे हैं।

तो, हालांकि अजीब, मुझे विश्वास नहीं है कि यह असंगत है।

+0

यह गलत है।'ए = ए || 1' '(ए = ए) || के रूप में पार्स नहीं करता है 1'। यह 'ए = (ए || 1)' के रूप में विश्लेषण करता है, इसलिए "ए को असाइन करने" के नतीजे के साथ इसका कोई लेना-देना नहीं है, क्योंकि किसी को कभी असाइन नहीं किया जाता है। – sepp2k

+0

@ sepp2k: मैं बिल्कुल यह कहने की कोशिश नहीं कर रहा था। मुझे खेद है अगर मैंने आपको भ्रमित कर दिया। मेरा मानना ​​है कि जोर्ग ने इसे और अधिक स्पष्ट रूप से समझाया है। – Cetra

0

क्या इसका मतलब है?

if !(defined? a) then 
    a = 1 
end 

डिफ़ॉल्ट रूप से 1 के साथ मान घोषित करना आसान हो सकता है।