रूबी में निम्नलिखित कोड का क्या अर्थ है?
||=
क्या इसका सिंटैक्स का कोई अर्थ या कारण है?
रूबी में निम्नलिखित कोड का क्या अर्थ है?
||=
क्या इसका सिंटैक्स का कोई अर्थ या कारण है?
जवाबों:
रूबी मेलिंग-लिस्ट और रूबी ब्लॉग पर इस सवाल पर इतनी बार चर्चा की गई है कि अब रूबी मेलिंग-लिस्ट पर भी थ्रेड्स हैं, जिसका एकमात्र उद्देश्य रूबी मेलिंग-लिस्ट पर अन्य सभी थ्रेड्स के लिंक एकत्र करना है जो इस मुद्दे पर है ।
यहाँ एक है: की निश्चित सूची || = (या समान) थ्रेड्स और पेज
यदि आप वास्तव में जानना चाहते हैं कि क्या हो रहा है, तो रूबी लैंग्वेज ड्राफ्ट स्पेसिफिकेशन की धारा 11.4.2.3 "संक्षिप्त कार्य" पर एक नज़र डालें ।
पहले सन्निकटन के रूप में,
a ||= b
के बराबर है
a || a = b
और नहीं के बराबर है
a = a || b
हालांकि, यह केवल एक पहला अनुमान है, खासकर अगर a
अपरिभाषित है। शब्दार्थ भी इस बात पर निर्भर करता है कि यह एक साधारण चर असाइनमेंट है, एक विधि असाइनमेंट या एक अनुक्रमण असाइनमेंट:
a ||= b
a.c ||= b
a[c] ||= b
सभी अलग तरह से व्यवहार कर रहे हैं।
a = false; a ||= true
ऐसा नहीं करता है जो आपका जवाब कहता है कि यह एक "अति सूक्ष्म अंतर" है।
a ||= b
एक सशर्त असाइनमेंट ऑपरेटर है । इसका मतलब है कि यदि a
अपरिभाषित या गलत है , तो मूल्यांकन करें b
और a
परिणाम पर सेट करें । समान रूप से, यदि a
परिभाषित किया गया है और सत्यता का मूल्यांकन किया जाता है, तो b
मूल्यांकन नहीं किया जाता है, और कोई असाइनमेंट नहीं होता है। उदाहरण के लिए:
a ||= nil # => nil
a ||= 0 # => 0
a ||= 2 # => 0
foo = false # => false
foo ||= true # => true
foo ||= false # => true
भ्रामक रूप से, यह अन्य असाइनमेंट ऑपरेटरों (जैसे +=
) के समान दिखता है , लेकिन अलग तरह से व्यवहार करता है।
a += b
में अनुवाद करता है a = a + b
a ||= b
मोटे तौर पर अनुवाद करता है a || a = b
यह एक निकट-आशुलिपि है a || a = b
। अंतर यह है कि, जब a
अपरिभाषित a || a = b
होता है , तो उठाता है NameError
, जबकि a ||= b
सेट करता a
है b
। इस तरह के अंतर महत्वहीन है अगर a
और b
दोनों स्थानीय चर रहे हैं, लेकिन यदि या तो एक वर्ग का एक गेटर / सेटर विधि है महत्वपूर्ण है।
आगे की पढाई:
h = Hash.new(0); h[1] ||= 2
। अब दो संभावित विस्तार h[1] = h[1] || 2
बनाम पर विचार करें h[1] || h[1] = 2
। दोनों अभिव्यक्तियाँ मूल्यांकन करती हैं 0
लेकिन पहले अनावश्यक रूप से हैश के आकार को बढ़ाती है। शायद इसीलिए मैट्ज़ ने ||=
दूसरे विस्तार की तरह व्यवहार करना चुना । (मैं एक और उत्तर में जुड़े थ्रेड्स में से एक से एक उदाहरण पर आधारित है।)
a || a = b
उठाता है NameError
अगर a
एक अपरिभाषित है। a ||= b
नहीं करता है, लेकिन इसके बजाय a
इसे इनिशियलाइज़ और सेट करता है b
। जहाँ तक मुझे पता है, दोनों के बीच यही एकमात्र अंतर है। इसी तरह, मेरे a = a || b
और a ||= b
मेरे बीच का एकमात्र अंतर यह है कि अगर a=
कोई तरीका है, तो यह a
रिटर्न की परवाह किए बिना कहा जाएगा । इसके अलावा, केवल बीच का अंतर a = b unless a
और a ||= b
है कि मैं के बारे में पता कर रहा हूँ कि है कि बयान मूल्यांकन करता है nil
के बजाय a
अगर a
truthy है। सन्निकटन के बहुत सारे, लेकिन कुछ भी नहीं के बराबर ...
a ||= b
निम्न पंक्तियों में से प्रत्येक के समान तरीके का मूल्यांकन करता है
a || a = b
a ? a : a = b
if a then a else a = b end
-
दूसरी ओर,
a = a || b
निम्न पंक्तियों में से प्रत्येक के समान तरीके का मूल्यांकन करता है
a = a ? a : b
if a then a = a else a = b end
-
संपादित करें: जैसा कि AJedi32 ने टिप्पणी में बताया है, यह केवल सच है अगर: 1. एक परिभाषित चर है। 2. एक बार और दो बार मूल्यांकन करने से कार्यक्रम या सिस्टम स्थिति में अंतर नहीं होता है।
a
गलत / शून्य / अपरिभाषित है, तो इसका दो बार मूल्यांकन किया जाता है। (लेकिन मैं रूबी को नहीं जानता, इसलिए मुझे नहीं पता कि अगर लैवल्स का सही मूल्यांकन किया जा सकता है ...)
a || a = b
, a ? a : a = b
, if a then a else a = b end
, और if a then a = a else a = b end
एक त्रुटि है, तो फेंक होगा a
अपरिभाषित है, जबकि a ||= b
और a = a || b
नहीं होगा। इसके अलावा, a || a = b
, a ? a : a = b
, if a then a else a = b end
, a = a ? a : b
, और if a then a = a else a = b end
मूल्यांकन a
दो बार जब a
truthy है, जबकि a ||= b
और a = a || b
नहीं है।
a || a = b
मूल्यांकन नहीं करेगा । a
a
the end state will be equivalent after the whole line has been evaluated
हालांकि यह जरूरी नहीं है कि सच हो। क्या होगा अगर a
एक विधि है? तरीकों के दुष्प्रभाव हो सकते हैं। साथ उदाहरण के लिए public; def a=n; @a=n; end; def a; @a+=1; end; self.a = 5
, self.a ||= b
6 वापस आ जाएगी, लेकिन self.a ? self.a : self.a = b
7. वापस आ जाएगी
इसका मतलब है या इसके बराबर है। यह देखने के लिए जांचता है कि क्या बाईं ओर मान परिभाषित किया गया है, तो इसका उपयोग करें। यदि यह नहीं है, तो दाईं ओर मान का उपयोग करें। आप इसका उपयोग मॉडल में चर को कैश करने के लिए रेल में कर सकते हैं।
एक त्वरित रेल-आधारित उदाहरण, जहां हम उपयोगकर्ता में वर्तमान में लॉग इन करने के लिए एक फ़ंक्शन बनाते हैं:
class User > ActiveRecord::Base
def current_user
@current_user ||= User.find_by_id(session[:user_id])
end
end
यह देखने के लिए जाँच करता है कि @current_user आवृत्ति चर सेट है या नहीं। यदि यह है, तो यह इसे वापस कर देगा, जिससे डेटाबेस कॉल की बचत होगी। यदि यह सेट नहीं है, तो हम कॉल करते हैं और फिर @current_user वैरिएबल को उस पर सेट करते हैं। यह वास्तव में सरल कैशिंग तकनीक है, लेकिन जब आप एक ही उदाहरण चर को कई बार अनुप्रयोग में ला रहे हों तो यह बहुत अच्छा है।
undefined
, बल्कि इस पर false
और nil
, जो शायद इसके लिए प्रासंगिक नहीं है current_user
, लेकिन विशेष false
रूप से अन्य मामलों में unexpectecd हो सकता है
x ||= y
है
x || x = y
"यदि x गलत या अपरिभाषित है, तो x बिंदु y से"
सटीक होने का a ||= b
अर्थ है , "यदि a
अपरिभाषित या मिथ्या ( false
या nil
) है, तो (यानी वापसी) के लिए निर्धारित a
करें b
और मूल्यांकन करें b
, अन्यथा मूल्यांकन करें a
"।
अन्य अक्सर यह कहकर इसका उदाहरण देने की कोशिश करते हैं कि a ||= b
यह a || a = b
या के बराबर है a = a || b
। ये समतुल्यताएं अवधारणा को समझने के लिए सहायक हो सकती हैं, लेकिन ध्यान रखें कि वे सभी परिस्थितियों में सटीक नहीं हैं। मुझे समझाने की अनुमति दें:
a ||= b
⇔a || a = b
?
जब a
एक अपरिभाषित स्थानीय चर होता है तो इन कथनों का व्यवहार भिन्न होता है। उस मामले में, a ||= b
सेट हो जाएगा a
करने के लिए b
(और का मूल्यांकन b
), जबकि a || a = b
इच्छा बढ़ाने NameError: undefined local variable or method 'a' for main:Object
।
a ||= b
⇔a = a || b
?
इन बयानों में से समानक अक्सर माना जाता है, के बाद से एक ऐसी ही तुल्यता अन्य के लिए सच है संक्षिप्त असाइनमेंट ऑपरेटरों (यानी +=
, -=
, *=
, /=
, %=
, **=
, &=
, |=
, ^=
, <<=
, और >>=
)। हालाँकि, ||=
इन कथनों के व्यवहार में भिन्नता तब हो सकती है जब a=
किसी वस्तु पर विधि हो और a
सत्य हो। उस मामले में, a ||= b
कुछ भी नहीं है (के रूप में मूल्यांकित के अलावा अन्य क्या करेंगे a
, जबकि) a = a || b
फोन करेगा a=(a)
पर a
है रिसीवर। जैसा कि अन्य लोगों ने बताया है, कॉलिंग a=a
के साइड इफेक्ट्स होने पर इससे फर्क पड़ सकता है, जैसे कि हैश में कीज़ जोड़ना।
a ||= b
⇔a = b unless a
??
इन कथनों का व्यवहार केवल उन बातों में भिन्न होता है, जिनका वे मूल्यांकन करते हैं a
कि सत्य कब है। उस स्थिति में, (हालांकि अभी भी सेट नहीं किया जाएगा , a = b unless a
उम्मीद के मुताबिक ) का मूल्यांकन करेगा , जबकि मूल्यांकन करेगा ।nil
a
a ||= b
a
a ||= b
⇔defined?(a) ? (a || a = b) : (a = b)
????
अभी भी नहीं। ये कथन अलग-अलग हो सकते हैं जब एक method_missing
विधि मौजूद होती है जो कि एक सत्य मान देता है a
। इस मामले में, a ||= b
जो कुछ भी करने के लिए मूल्यांकन करेंगे method_missing
रिटर्न, और सेट करने का प्रयास नहीं a
है, जबकि defined?(a) ? (a || a = b) : (a = b)
सेट हो जाएगा a
करने के लिए b
और करने के लिए मूल्यांकन b
।
ठीक है, ठीक है, तो इसके बराबर क्या है a ||= b
? क्या रूबी में इसे व्यक्त करने का कोई तरीका है?
ठीक है, यह मानते हुए कि मैं कुछ भी अनदेखी नहीं कर रहा हूं, मेरा मानना a ||= b
है कि कार्यात्मक रूप से इसके बराबर है ... ( ड्रमोल )
begin
a = nil if false
a || a = b
end
रुको! इससे पहले कि यह एक noop के साथ सिर्फ पहला उदाहरण नहीं है? खैर, काफी नहीं। याद रखें मैं कैसे कहा पहले कि a ||= b
केवल के बराबर नहीं है a || a = b
जब a
एक अपरिभाषित स्थानीय चर रहा है? ठीक है, a = nil if false
यह सुनिश्चित करता है कि a
कभी भी अपरिभाषित न हो, भले ही उस लाइन को कभी निष्पादित नहीं किया गया हो। रूबी में स्थानीय चर लेक्सिक रूप से स्कोप किए गए हैं।
(a=b unless a) or a
a
एक विधि है, तो इसे एक बार के बजाय दो बार कहा जाएगा (यदि यह पहली बार एक सत्य मान लौटाता है)। उदाहरण के लिए, व्यवहार में भिन्नता उत्पन्न हो सकती है, यदि a
लौटने में लंबा समय लगता है या इसके दुष्प्रभाव होते हैं।
b
करने के लिएa
दूसरे शब्दों में, आरएचएस अभी भी एलएचएस को असाइन नहीं है, या, एलएचएस अभी भी आरएचएस लिए अपने मूल्य निर्धारित नहीं करता है?
a ||= b
जवाब मैंने इंटरनेट पर पाया है। धन्यवाद।
मान लीजिए a = 2
औरb = 3
फिर, a ||= b
इसका परिणाम a
मूल्य होगा 2
।
जब कुछ मूल्य के लिए एक मूल्यांकन के परिणामस्वरूप false
या नहीं nil
.. यही कारण है कि यह मूल्य का ll
मूल्यांकन नहीं है b
।
अब मान लीजिए a = nil
और b = 3
।
तब यानी के मूल्य के a ||= b
लिए परिणाम होगा ।3
b
चूंकि यह पहली बार किसी मूल्य का मूल्यांकन करने का प्रयास करता है जिसके परिणामस्वरूप nil
.. इसलिए इसका मूल्यांकन किया गया है b
।
रोर ऐप में उपयोग किया जाने वाला सबसे अच्छा उदाहरण है:
#To get currently logged in iser
def current_user
@current_user ||= User.find_by_id(session[:user_id])
end
# Make current_user available in templates as a helper
helper_method :current_user
कहाँ, User.find_by_id(session[:user_id])
अगर और केवल @current_user
पहले शुरू नहीं किया गया है , तो निकाल दिया जाता है।
ए = = बी
यह दर्शाता है कि यदि कोई मान 'a' में मौजूद है और आप उस मूल्य का उपयोग करते हुए उसे बदलना नहीं चाहते हैं, तो यदि 'a' में कोई मान नहीं है, तो 'b' का उपयोग करें।
सरल शब्द, यदि बाएं हाथ की तरफ शून्य नहीं है, तो मौजूदा मूल्य पर इंगित करें, और दाईं ओर मान पर इंगित करें।
a ||= b
के बराबर है
a || a = b
और नहीं
a = a || b
उस स्थिति के कारण जहां आप डिफ़ॉल्ट के साथ हैश को परिभाषित करते हैं (हैश किसी भी अपरिभाषित कुंजी के लिए डिफ़ॉल्ट लौटाएगा)
a = Hash.new(true) #Which is: {}
यदि तुम प्रयोग करते हो:
a[10] ||= 10 #same as a[10] || a[10] = 10
एक अभी भी है:
{}
लेकिन जब आप इसे ऐसा लिखते हैं:
a[10] = a[10] || 10
एक हो जाता है:
{10 => true}
क्योंकि आपने कुंजी पर स्वयं के मान को असाइन किया है 10
, जो कि सत्य के लिए चूक है, इसलिए अब हैश को कुंजी के लिए परिभाषित किया गया है 10
, न कि पहली जगह में असाइनमेंट का प्रदर्शन करने के बजाय।
कृपया यह भी याद रखें कि ||=
परमाणु ऑपरेशन नहीं है और इसलिए, यह थ्रेड सुरक्षित नहीं है। अंगूठे के नियम के रूप में, इसे कक्षा के तरीकों के लिए उपयोग न करें।
यह डिफ़ॉल्ट असाइनमेंट नोटेशन है
उदाहरण के लिए: x || = 1
यह देखने के लिए जाँच करेगा कि क्या x शून्य है या नहीं। यदि x वास्तव में शून्य है तो वह इसे नया मान देगा (1 हमारे उदाहरण में)
अधिक स्पष्ट:
यदि x == नील
x = 1
छोर
nil
या false
, न केवलnil
||=
केवल दाएं को मान प्रदान करता है यदि बाईं ओर == नील (या अपरिभाषित या गलत है)।
यह रूबी-लैंग सिंटैक्स। सही उत्तर माणिक-लैंग प्रलेखन की जांच करना है। अन्य सभी स्पष्टीकरणों को मानते हैं ।
"रूबी-लैंग डॉक्स संक्षिप्त रूप से असाइनमेंट"।
https://docs.ruby-lang.org/en/2.4.0/syntax/assignment_rdoc.html#label-Abbreviated+Assignment
b = 5
a ||= b
इसका अनुवाद इस प्रकार है:
a = a || b
कोनसा होगा
a = nil || 5
तो आखिरकार
a = 5
अब अगर आप इसे दोबारा कहते हैं:
a ||= b
a = a || b
a = 5 || 5
a = 5
b = 6
अब अगर आप इसे दोबारा कहते हैं:
a ||= b
a = a || b
a = 5 || 6
a = 5
यदि आप निरीक्षण करते हैं, तो b
मान असाइन नहीं किया जाएगा a
। a
अभी भी होगा5
।
रूबी में एक्सेसर्स को गति देने के लिए इसका एक मेमोनाइजेशन पैटर्न।
def users
@users ||= User.all
end
यह मूल रूप से अनुवाद करता है:
@users = @users || User.all
तो आप पहली बार डेटाबेस को कॉल करेंगे आप इस विधि को कॉल करते हैं।
इस विधि के लिए भविष्य की कॉल @users
उदाहरण चर का मान लौटाएगी।
||=
को सशर्त असाइनमेंट ऑपरेटर कहा जाता है।
यह मूल रूप से काम करता है, =
लेकिन इस अपवाद के साथ कि अगर एक चर पहले ही सौंपा गया है तो यह कुछ नहीं करेगा।
पहला उदाहरण:
x ||= 10
दूसरा उदाहरण:
x = 20
x ||= 10
पहले उदाहरण x
में अब 10 के बराबर है। हालांकि, दूसरे उदाहरण x
में पहले से ही 20 के रूप में परिभाषित किया गया है। इसलिए सशर्त ऑपरेटर का कोई प्रभाव नहीं है। x
दौड़ने के बाद भी 20 है x ||= 10
।
a ||= b
कहने जैसा ही है a = b if a.nil?
याa = b unless a
लेकिन क्या सभी 3 विकल्प समान प्रदर्शन दिखाते हैं? रूबी 2.5.1 के साथ यह
1000000.times do
a ||= 1
a ||= 1
a ||= 1
a ||= 1
a ||= 1
a ||= 1
a ||= 1
a ||= 1
a ||= 1
a ||= 1
end
मेरे पीसी पर 0.099 सेकंड लेता है, जबकि
1000000.times do
a = 1 unless a
a = 1 unless a
a = 1 unless a
a = 1 unless a
a = 1 unless a
a = 1 unless a
a = 1 unless a
a = 1 unless a
a = 1 unless a
a = 1 unless a
end
0.062 सेकंड लेता है। यह लगभग 40% तेज है।
और फिर हमारे पास भी है:
1000000.times do
a = 1 if a.nil?
a = 1 if a.nil?
a = 1 if a.nil?
a = 1 if a.nil?
a = 1 if a.nil?
a = 1 if a.nil?
a = 1 if a.nil?
a = 1 if a.nil?
a = 1 if a.nil?
a = 1 if a.nil?
end
जो 0.166 सेकंड लेता है।
ऐसा नहीं है कि यह सामान्य रूप से एक महत्वपूर्ण प्रदर्शन प्रभाव डालेगा, लेकिन यदि आपको उस अंतिम बिट अनुकूलन की आवश्यकता है, तो इस परिणाम पर विचार करें। वैसे:a = 1 unless a
नौसिखिए के लिए पढ़ना आसान है, यह आत्म-व्याख्यात्मक है।
नोट 1: असाइनमेंट लाइन को कई बार दोहराने का कारण मापा समय पर लूप के ओवरहेड को कम करना है।
नोट 2: यदि मैं a=nil
प्रत्येक असाइनमेंट से पहले शून्य करता हूं तो परिणाम समान हैं ।