डीकंपोज़िशन का मतलब है किसी कलेक्शन, जैसे Array या Hash, के एलिमेंट अलग-अलग निकालना। इस तरह अलग की गई वैल्यू को उसी स्टेटमेंट में वेरिएबलो को असाइन किया जा सकता है।
मल्टीपल असाइनमेंट एक ही स्टेटमेंट में कई वेरिएबलो को वैल्यू असाइन करने की सुविधा है। इससे कोड ज़्यादा छोटा और पढ़ने में आसान हो जाता है। इसके लिए जिन वेरिएबलो को असाइन करना है, उन्हें कॉमा से अलग किया जाता है, जैसे first, second, third = [1, 2, 3]।
स्प्लैट ऑपरेटर (*) और डबल स्प्लैट ऑपरेटर (**) का इस्तेमाल अक्सर डीकंपोज़िशन में होता है। स्प्लैट ऑपरेटर (*) की मदद से कई ऐरे को मिलाकर एक ऐरे बनाया जा सकता है; इसके लिए हर ऐरे को डीकंपोज़ करके एक नए साझा ऐरे में रखा जाता है। डबल स्प्लैट ऑपरेटर (**) की मदद से कई डिक्शनरी को मिलाकर एक डिक्शनरी बनाई जा सकती है; इसके लिए हर डिक्शनरी को डीकंपोज़ करके एक नई साझा डिक्शनरी में रखा जाता है। यह सिंटैक्स इस फ़र्क को साफ़ करता है: कहीं हम पोज़िशनल आर्गुमेंट के रूप में कई वैल्यू लेते हैं, तो कहीं कितने भी कीवर्ड आर्गुमेंट लेते हैं।
जब स्प्लैट ऑपरेटर (*) का इस्तेमाल बिना किसी कलेक्शन के किया जाता है, तो यह कई वैल्यू को पैक (यानी कंपोज़) करके एक ऐरे बना देता है। मल्टीपल असाइनमेंट में इसका इस्तेमाल अक्सर बाकी बचे उन सभी एलिमेंट को एक ही वेरिएबल में डालने के लिए किया जाता है जिनके लिए अलग-अलग असाइनमेंट नहीं दिए गए हैं।
Ruby में ऐसे मेथड बनाते या इस्तेमाल करते समय यह डीकंपोज़/कंपोज़ करने वाला व्यवहार आम है जो कितने भी पोज़िशनल या कीवर्ड आर्गुमेंट लेते हैं। आप अक्सर देखेंगे कि ऐसे आर्गुमेंट def some_method(*arguments, **keyword_arguments) की तरह परिभाषित किए जाते हैं और some_method(*some_array, **some_hash) की तरह इस्तेमाल किए जाते हैं।
*<variable_name> और **<variable_name> को * और ** से भ्रमित नहीं किया जाना चाहिए।
जहाँ * और ** क्रमशः गुणा और घात के लिए इस्तेमाल होते हैं, वहीं *<variable_name> और **<variable_name> कंपोज़िशन और डीकंपोज़िशन ऑपरेटर के रूप में इस्तेमाल होते हैं।
मल्टीपल असाइनमेंट से आप एक ही लाइन में कई वेरिएबलो को वैल्यू असाइन कर सकते हैं। वैल्यू को अलग करने के लिए कॉमा , लगाइए:
>> a, b = 1, 2
=> [1, 2]
>> a
=> 1
मल्टीपल असाइनमेंट किसी एक डेटा टाइप तक सीमित नहीं है:
>> x, y, z = 1, "Hello", true
=> [1, "Hello", true]
>> x
=> 1
>> y
=> 'Hello'
>> z
=> true
मल्टीपल असाइनमेंट का इस्तेमाल ऐरे के एलिमेंट आपस में बदलने के लिए किया जा सकता है। सॉर्टिंग एल्गोरिदम में यह तरीका काफी आम है। उदाहरण के लिए:
>> numbers = [1, 2]
=> [1, 2]
>> numbers[0], numbers[1] = numbers[1], numbers[0]
=> [2, 1]
>> numbers
=> [2, 1]
इसे "पैरेलल असाइनमेंट" भी कहा जाता है, और इसका इस्तेमाल एक अस्थायी वेरिएबल से बचने के लिए किया जा सकता है।
अगर वैल्यू से ज़्यादा वेरिएबल हों, तो अतिरिक्त वेरिएबलो को nil असाइन किया जाता है:
>> a, b, c = 1, 2
=> [1, 2]
>> b
=> 2
>> c
=> nil
अगर वेरिएबल से ज़्यादा वैल्यू हों, तो अतिरिक्त वैल्यू छोड़ दी जाती हैं:
>> a, b, c = 1, 2, 3, 4
>> b
=> 2
>> c
=> 3
Ruby में ऐरे/डिक्शनरी के एलिमेंट को अलग-अलग वेरिएबलो में डीकंपोज़ किया जा सकता है। चूँकि ऐरे में वैल्यू इंडेक्स क्रम में रहती हैं, इसलिए उन्हें भी उसी क्रम में वेरिएबलो में खोला जाता है:
>> fruits = ["apple", "banana", "cherry"]
>> x, y, z = fruits
>> x
=> "apple"
अगर कुछ वैल्यू की ज़रूरत नहीं है, तो _ लगाकर बता सकते हैं कि उन्हें इकट्ठा तो किया गया है, पर इस्तेमाल नहीं किया जाएगा:
>> fruits = ["apple", "banana", "cherry"]
>> _, _, z = fruits
>> z
=> "cherry"
किसी ऐरे के अंदर मौजूद ऐरे (जिसे नेस्टेड ऐरे भी कहते हैं) से वैल्यू डीकंपोज़ करके असाइन करना सतही डीकंपोज़िशन की तरह ही काम करता है, लेकिन वैल्यू का संदर्भ या स्थान साफ़ करने के लिए इसमें सीमांकित डीकंपोज़िशन एक्सप्रेशन (()) की ज़रूरत पड़ती है:
>> fruits_vegetables = [["apple", "banana"], ["carrot", "potato"]]
>> (a, b), (c, d) = fruits_vegetables
>> a
=> "apple"
>> d
=> "potato"
आप किसी नेस्टेड ऐरे के सिर्फ एक हिस्से को भी गहराई तक खोल सकते हैं:
>> fruits_vegetables = [["apple", "banana"], ["carrot", "potato"]]
>> a, (c, d) = fruits_vegetables
>> a
=> ["apple", "banana"]
>> c
=> "carrot"
अगर डीकंपोज़िशन में वेरिएबलो की जगह गलत हो या वैल्यू की संख्या गलत हो, तो आपको सिंटैक्स एरर मिलेगी:
fruits_vegetables = [["apple", "banana"], ["carrot", "potato"]]
(a, b), (d) = fruits_vegetables
syntax error, unexpected ')', expecting '.' or &. or :: or '['
((a, b), (d)) = fruits_vegetables
यहाँ प्रयोग करके देखिए, आप पाएँगे कि तय पहला पैटर्न करता है, दाईं ओर की उपलब्ध वैल्यू नहीं। यह सिंटैक्स एरर डेटा स्ट्रक्चर से जुड़ी नहीं है।
*) से ऐरे को डीकंपोज़ करनाकिसी ऐरे को [डीकंपोज़ करते समय][decomposition] आप स्प्लैट ऑपरेटर (*) से बची हुई वैल्यू पकड़ सकते हैं। यह ऐरे को स्लाइस करने से ज़्यादा साफ़ है (जो कुछ स्थितियों में कम पढ़ने योग्य होता है)। उदाहरण के लिए, हम पहला एलिमेंट निकाल सकते हैं और बाकी वैल्यू को पहले एलिमेंट के बिना एक नए ऐरे में असाइन कर सकते हैं:
>> fruits = ["apple", "banana", "cherry", "orange", "kiwi", "melon", "mango"]
>> x, *last = fruits
>> x
=> "apple"
>> last
=> ["banana", "cherry", "orange", "kiwi", "melon", "mango"]
हम ऐरे के शुरू और अंत की वैल्यू निकालकर बीच की सारी वैल्यू को एक साथ भी रख सकते हैं:
>> fruits = ["apple", "banana", "cherry", "orange", "kiwi", "melon", "mango"]
>> x, *middle, y, z = fruits
>> y
=> "melon"
>> middle
=> ["banana", "cherry", "orange", "kiwi"]
गहरे डीकंपोज़िशन में भी * का इस्तेमाल किया जा सकता है:
>> fruits_vegetables = [["apple", "banana", "melon"], ["carrot", "potato", "tomato"]]
>> (a, *rest), b = fruits_vegetables
>> a
=> "apple"
>> rest
=> ["banana", "melon"]
Hash को डीकंपोज़ करनाडिक्शनरी को डीकंपोज़ करना ऐरे को डीकंपोज़ करने से थोड़ा अलग है। डिक्शनरी को खोलने के लिए पहले उसे ऐरे में बदलना पड़ता है। ऐसा न करने पर डीकंपोज़िशन नहीं होगा:
>> fruits_inventory = {apple: 6, banana: 2, cherry: 3}
>> x, y, z = fruits_inventory
>> x
=> {:apple=>6, :banana=>2, :cherry=>3}
>> y
=> nil
किसी Hash को ऐरे में बदलने के लिए आप to_a मेथड इस्तेमाल कर सकते हैं:
>> fruits_inventory = {apple: 6, banana: 2, cherry: 3}
>> fruits_inventory.to_a
=> [[:apple, 6], [:banana, 2], [:cherry, 3]]
>> x, y, z = fruits_inventory.to_a
>> x
=> [:apple, 6]
अगर आप हैश में मौजूद की खोलना चाहते हैं, तो keys मेथड इस्तेमाल कीजिए:
>> fruits_inventory = {apple: 6, banana: 2, cherry: 3}
>> x, y, z = fruits_inventory.keys
>> x
=> :apple
अगर आप हैश में मौजूद वैल्यू खोलना चाहते हैं, तो values मेथड इस्तेमाल कीजिए:
>> fruits_inventory = {apple: 6, banana: 2, cherry: 3}
>> x, y, z = fruits_inventory.values
>> x
=> 6
कंपोज़ करने का मतलब है कई वैल्यू को एक ऐरे में इकट्ठा करके किसी वेरिएबल को सौंपना। यह तब काम आता है जब आप वैल्यू को डीकंपोज़ करना, उनमें बदलाव करना और फिर नतीजों को कंपोज़ करके वापस एक वेरिएबल में रखना चाहते हैं। इससे दो या अधिक ऐरे/डिक्शनरी पर मर्ज करना भी संभव हो जाता है।
*) से ऐरे का कंपोज़िशनकिसी ऐरे को स्प्लैट ऑपरेटर (*) से कंपोज़ किया जा सकता है। यह सारी वैल्यू को एक ऐरे में पैक कर देता है।
>> fruits = ["apple", "banana", "cherry"]
>> more_fruits = ["orange", "kiwi", "melon", "mango"]
# fruits and more_fruits are unpacked and then their elements are packed into combined_fruits
>> combined_fruits = *fruits, *more_fruits
>> combined_fruits
=> ["apple", "banana", "cherry", "orange", "kiwi", "melon", "mango"]
**) से हैश का कंपोज़िशनहैश को डबल स्प्लैट ऑपरेटर (**) से कंपोज़ किया जाता है। यह एक हैश के सारे की/वैल्यू जोड़े दूसरे हैश में पैक कर देता है, या दो हैश को आपस में मिला देता है।
>> fruits_inventory = {apple: 6, banana: 2, cherry: 3}
>> more_fruits_inventory = {orange: 4, kiwi: 1, melon: 2, mango: 3}
# fruits_inventory and more_fruits_inventory are unpacked into key-values pairs and combined.
>> combined_fruits_inventory = {**fruits_inventory, **more_fruits_inventory}
# then the pairs are packed into combined_fruits_inventory
>> combined_fruits_inventory
=> {:apple=>6, :banana=>2, :cherry=>3, :orange=>4, :kiwi=>1, :melon=>2, :mango=>3}
*) और डबल स्प्लैट ऑपरेटर (**) का इस्तेमालजब आप ऐसा मेथड बनाते हैं जो कितने भी आर्गुमेंट ले सकता है, तो मेथड की परिभाषा में *arguments या **keyword_arguments इस्तेमाल कर सकते हैं। *arguments कितने भी पोज़िशनल (गैर-कीवर्ड) आर्गुमेंट को पैक करने के लिए इस्तेमाल होता है और **keyword_arguments कितने भी कीवर्ड आर्गुमेंट को पैक करने के लिए।
*arguments का इस्तेमाल:
# This method is defined to take any number of positional arguments
# (Using the single line form of the definition of a method.)
>> def my_method(*arguments)= arguments
# Arguments given to the method are packed into an array
>> my_method(1, 2, 3)
=> [1, 2, 3]
>> my_method("Hello")
=> ["Hello"]
>> my_method(1, 2, 3, "Hello", "Mars")
=> [1, 2, 3, "Hello", "Mars"]
**keyword_arguments का इस्तेमाल:
# This method is defined to take any number of keyword arguments
>> def my_method(**keyword_arguments)= keyword_arguments
# Arguments given to the method are packed into a dictionary
>> my_method(a: 1, b: 2, c: 3)
=> {:a => 1, :b => 2, :c => 3}
अगर बनाए गए मेथड में कीवर्ड आर्गुमेंट के लिए कोई पैरामीटर तय नहीं है (**keyword_arguments या <key_word>: <value>), तो कीवर्ड आर्गुमेंट एक हैश में पैक होकर अंतिम पैरामीटर को असाइन कर दिए जाते हैं।
>> def my_method(a)= a
>> my_method(a: 1, b: 2, c: 3)
=> {:a => 1, :b => 2, :c => 3}
*arguments और **keyword_arguments को एक साथ मिलाकर भी इस्तेमाल किया जा सकता है:
def my_method(*arguments, **keyword_arguments)
p arguments.sum
for (key, value) in keyword_arguments.to_a
p key.to_s + " = " + value.to_s
end
end
my_method(1, 2, 3, a: 1, b: 2, c: 3)
6
"a = 1"
"b = 2"
"c = 3"
आप *arguments से पहले और बाद में भी आर्गुमेंट लिख सकते हैं, ताकि कुछ खास पोज़िशनल आर्गुमेंट तय किए जा सकें। यह ऐरे को डीकंपोज़ करने की तरह ही काम करता है।
आर्गुमेंट को एक तय क्रम में ही लिखा जाना चाहिए:
def my_method(<positional_arguments>, *arguments, <positional_arguments>, <key-word_arguments>, **keyword_arguments)
अगर आप इस क्रम का पालन नहीं करते, तो आपको एरर मिलेगी।
def my_method(a, b, *arguments)
p a
p b
p arguments
end
my_method(1, 2, 3, 4, 5)
1
2
[3, 4, 5]
आप *arguments से पहले और बाद में पोज़िशनल आर्गुमेंट लिख सकते हैं:
>> def my_method(a, *middle, b)= middle
>> my_method(1, 2, 3, 4, 5)
=> [2, 3, 4]
आप पोज़िशनल आर्गुमेंट, *arguments, कीवर्ड आर्गुमेंट और **keyword_arguments को भी एक साथ मिला सकते हैं:
>> def my_method(first, *many, last, a:, **keyword_arguments)
p first
p many
p last
p a
p keyword_arguments
end
>> my_method(1, 2, 3, 4, 5, a: 6, b: 7, c: 8)
1
[2, 3, 4]
5
6
{:b => 7, :c => 8}
आर्गुमेंट को गलत क्रम में लिखने पर एरर मिलेगी:
def my_method(a:, **keyword_arguments, first, *arguments, last)
arguments
end
my_method(1, 2, 3, 4, a: 5)
syntax error, unexpected local variable or method, expecting & or '&'
... my_method(a:, **keyword_arguments, first, *arguments, last)
आप मेथड कॉल में आर्गुमेंट की ऐरे को खोलने के लिए स्प्लैट ऑपरेटर (*) इस्तेमाल कर सकते हैं:
def my_method(a, b, c)
p c
p b
p a
end
numbers = [1, 2, 3]
my_method(*numbers)
3
2
1
आप मेथड कॉल में आर्गुमेंट की डिक्शनरी को खोलने के लिए डबल स्प्लैट ऑपरेटर (**) भी इस्तेमाल कर सकते हैं:
def my_method(a:, b:, c:)
p c
p b
p a
end
numbers = {a: 1, b: 2, c: 3}
my_method(**numbers)
3
2
1