रूबी में निम्नलिखित कोड का क्या अर्थ है?
||=
क्या इसका सिंटैक्स का कोई अर्थ या कारण है?
रूबी में निम्नलिखित कोड का क्या अर्थ है?
||=
क्या इसका सिंटैक्स का कोई अर्थ या कारण है?
जवाबों:
रूबी मेलिंग-लिस्ट और रूबी ब्लॉग पर इस सवाल पर इतनी बार चर्चा की गई है कि अब रूबी मेलिंग-लिस्ट पर भी थ्रेड्स हैं, जिसका एकमात्र उद्देश्य रूबी मेलिंग-लिस्ट पर अन्य सभी थ्रेड्स के लिंक एकत्र करना है जो इस मुद्दे पर है ।
यहाँ एक है: की निश्चित सूची || = (या समान) थ्रेड्स और पेज
यदि आप वास्तव में जानना चाहते हैं कि क्या हो रहा है, तो रूबी लैंग्वेज ड्राफ्ट स्पेसिफिकेशन की धारा 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 + ba ||= 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अगर atruthy है। सन्निकटन के बहुत सारे, लेकिन कुछ भी नहीं के बराबर ...
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दो बार जब atruthy है, जबकि a ||= bऔर a = a || bनहीं है।
a || a = bमूल्यांकन नहीं करेगा । aa
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 ||= b6 वापस आ जाएगी, लेकिन self.a ? self.a : self.a = b7. वापस आ जाएगी
इसका मतलब है या इसके बराबर है। यह देखने के लिए जांचता है कि क्या बाईं ओर मान परिभाषित किया गया है, तो इसका उपयोग करें। यदि यह नहीं है, तो दाईं ओर मान का उपयोग करें। आप इसका उपयोग मॉडल में चर को कैश करने के लिए रेल में कर सकते हैं।
एक त्वरित रेल-आधारित उदाहरण, जहां हम उपयोगकर्ता में वर्तमान में लॉग इन करने के लिए एक फ़ंक्शन बनाते हैं:
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उम्मीद के मुताबिक ) का मूल्यांकन करेगा , जबकि मूल्यांकन करेगा ।nilaa ||= ba
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लिए परिणाम होगा ।3b
चूंकि यह पहली बार किसी मूल्य का मूल्यांकन करने का प्रयास करता है जिसके परिणामस्वरूप 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प्रत्येक असाइनमेंट से पहले शून्य करता हूं तो परिणाम समान हैं ।