रूबी दो मूल्यों को कैसे लौटाती है?


94

जब भी मैं किसी सरणी में मानों को स्वैप करता हूं, तो मुझे यकीन है कि मैंने एक संदर्भ चर में एक मान संग्रहीत किया है। लेकिन मैंने पाया कि रूबी दो मूल्यों के साथ-साथ दो मूल्यों को स्वचालित रूप से स्वैप कर सकती है। उदाहरण के लिए,

array = [1, 3, 5 , 6 ,7]
array[0], array[1] = array[1] , array[0] #=> [3, 1] 

मैं सोच रहा था कि रूबी ऐसा कैसे करती है।


9
तकनीकी रूप से रूबी दो मूल्यों को वापस नहीं करता है। यह एक सरणी वापस कर सकता है जो बदले में दो चर को सौंपा जाता है।
चार्ल्स कैलडवेल

जवाबों:


164

अन्य भाषाओं के विपरीत, रूबी में किसी भी विधि कॉल का रिटर्न मूल्य हमेशा एक वस्तु है। यह संभव है, क्योंकि रूबी में सब कुछ nilअपने आप में एक वस्तु है।

तीन बुनियादी पैटर्न हैं जो आप देखेंगे। कोई विशेष मूल्य नहीं लौटना:

def nothing
end

nothing
# => nil

एक विलक्षण मान लौटाना:

def single
  1
end

x = single
# => 1

यह अन्य प्रोग्रामिंग भाषाओं से आपकी अपेक्षा के अनुरूप है।

कई रिटर्न मूल्यों के साथ काम करते समय चीजें थोड़ी अलग हो जाती हैं। इन्हें स्पष्ट रूप से निर्दिष्ट करने की आवश्यकता है:

def multiple
  return 1, 2
end

x = multiple
# => [ 1, 2 ]
x
# => [ 1, 2 ]

कई मानों को लौटाने वाली कॉल करते समय, आप उन्हें स्वतंत्र चर में तोड़ सकते हैं:

x, y = multiple
# => [ 1, 2 ]
x
# => 1
y
# => 2

यह रणनीति उस प्रतिस्थापन के प्रकार के लिए भी काम करती है जिसके बारे में आप बात कर रहे हैं:

a, b = 1, 2
# => [1, 2]
a, b = b, a
# => [2, 1]
a
# => 2
b
# => 1

8
आप सावधानी से एक सरणी लौटा सकते हैं [1, 2]और यह ऊपर दिए गए उदाहरणों के समान ही काम करेगा।
हौलेथ

6
@ भावार्थ एक अच्छा अवलोकन। मैं यह स्पष्ट कर दिया है कि चाहिए 1,2अपने आप में अमान्य है, लेकिन या तो की return 1,2या [1,2]काम करते हैं।
tadman

50

नहीं, रूबी वास्तव में दो वस्तुओं को वापस करने का समर्थन नहीं करती है। (BTW: आप ऑब्जेक्ट्स लौटाते हैं, चर नहीं। अधिक सटीक रूप से, आप ऑब्जेक्ट्स पर पॉइंटर्स लौटाते हैं।)

हालांकि, यह समानांतर असाइनमेंट का समर्थन करता है। यदि आपके पास असाइनमेंट के दाईं ओर एक से अधिक ऑब्जेक्ट हैं, तो ऑब्जेक्ट्स को एक में एकत्रित किया जाता है Array:

foo = 1, 2, 3
# is the same as
foo = [1, 2, 3]

यदि आपके पास एक असाइनमेंट के बाईं ओर एक से अधिक "लक्ष्य" (वैरिएबल या सेटर विधि) है, तो वेरिएबल्स Arrayदाईं ओर के तत्वों से बंधे होते हैं :

a, b, c = ary
# is the same as
a = ary[0]
b = ary[1]
c = ary[2]

यदि दाहिने हाथ की तरफ एक नहीं है Array, तो इसे to_aryविधि का उपयोग करके एक में परिवर्तित किया जाएगा

a, b, c = not_an_ary
# is the same as
ary = not_an_ary.to_ary
a = ary[0]
b = ary[1]
c = ary[2]

और अगर हम दोनों को एक साथ रखते हैं, तो हमें वह मिल जाता है

a, b, c = d, e, f
# is the same as
ary = [d, e, f]
a = ary[0]
b = ary[1]
c = ary[2]

इससे संबंधित असाइनमेंट के बाईं ओर स्थित स्पैट ऑपरेटर है। इसका मतलब है " दाहिने हाथ की ओर के सभी बाएं-ओवर तत्वों को लें Array":

a, b, *c = ary
# is the same as
a = ary[0]
b = ary[1]
c = ary.drop(2) # i.e. the rest of the Array

और अंतिम लेकिन कम से कम नहीं, समानांतर असाइनमेंट को कोष्ठक का उपयोग करके घोंसला बनाया जा सकता है:

a, (b, c), d = ary
# is the same as
a = ary[0]
b, c = ary[1]
d = ary[2]
# which is the same as
a = ary[0]
b = ary[1][0]
c = ary[1][1]
d = ary[2]

जब आप returnकिसी विधि से nextया breakकिसी ब्लॉक से आते हैं, तो रूबी इस तरह का व्यवहार करेगी जैसे कि किसी असाइनमेंट के राइट-हैंड साइड,

return 1, 2
next 1, 2
break 1, 2
# is the same as
return [1, 2]
next [1, 2]
break [1, 2]

वैसे, यह विधियों और ब्लॉकों की पैरामीटर सूचियों में भी काम करता है (तरीकों के अधिक सख्त होने और कम सख्त ब्लॉक करने के लिए):

def foo(a, (b, c), d) p a, b, c, d end

bar {|a, (b, c), d| p a, b, c, d }

ब्लॉक "कम सख्त" उदाहरण के लिए है जो Hash#eachकाम करता है। यह वास्तव में ब्लॉक के लिए कुंजी और मूल्य का yieldएक एकल -तत्व Arrayहै, लेकिन हम आमतौर पर लिखते हैं

some_hash.each {|k, v| }

के बजाय

some_hash.each {|(k, v)| }

16

tadman और Jörg W Mittag रूबी को मुझसे बेहतर जानते हैं, और उनके जवाब गलत नहीं हैं, लेकिन मुझे नहीं लगता कि वे जवाब दे रहे हैं जो ओपी जानना चाहते थे। मुझे लगता है कि सवाल हालांकि स्पष्ट नहीं था। मेरी समझ में, ओपी जो पूछना चाहता था उसका कई मूल्यों को वापस करने से कोई लेना-देना नहीं है।


असली सवाल यह है कि जब आप दो चर के मानों को बदलना चाहते हैं aऔर b(या मूल प्रश्न के अनुसार किसी सरणी में दो स्थिति), तो एक अस्थायी चर का उपयोग करना क्यों आवश्यक नहीं है temp:

a, b = :foo, :bar
temp = a
a = b
b = temp

लेकिन सीधे किया जा सकता है जैसे:

a, b = :foo, :bar
a, b = b, a

इसका उत्तर यह है कि कई असाइनमेंट में, पूरे बाएं हाथ की तरफ पूरे बाएं हाथ के असाइनमेंट से पहले मूल्यांकन किया जाता है, और यह एक-एक करके नहीं किया जाता है। के a, b = b, aबराबर नहीं है a = b; b = a

असाइनमेंट से पहले पूरे दाहिने हाथ की ओर का मूल्यांकन करना एक आवश्यकता है जो समायोजन से होती है जब दोनों पक्षों में =अलग-अलग संख्याएँ होती हैं, और जोर्ग डब्ल्यू मित्तग का विवरण अप्रत्यक्ष रूप से संबंधित हो सकता है, लेकिन यह मुख्य मुद्दा नहीं है।


8

यदि आपके पास कुछ ही मूल्य हैं, तो ऐरे एक अच्छा विकल्प है। यदि आप परिणामों के क्रम को जाने बिना (और भ्रमित होकर) कई रिटर्न वैल्यू चाहते हैं, तो एक विकल्प हैश को वापस करना होगा जिसमें आपके द्वारा नामित मानों को शामिल करना है।

जैसे

def make_hash
  x = 1
  y = 2
  {x: x, y: y}
end

hash = make_hash
# => {:x=>1, :y=>2}
hash[:x]
# => 1
hash[:y]
# => 2
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.