क्यों करता है:
[1,2,3,4,5].map(&:to_s) #=> ["1", "2", "3", "4", "5"]
काम लेकिन
[1,2,3,4,5].map(&:*(2))
एक अप्रत्याशित वाक्यविन्यास त्रुटि फेंकता है?
उत्तर:
जवाब के लिए 3 № 1&
कहा जाता है to_proc
ऑपरेटर। यह कहते हैं to_proc
अभिव्यक्ति पर विधि जो इसका अनुसरण करती है और उसके बाद परिणामी प्रक्रिया को ब्लॉक के रूप में विधि में पास करती है।
के मामले में &:to_s
, :to_s
एक प्रतीक है, इसलिए यह ऑपरेटर कॉल करता है Symbol#to_proc
। दस्तावेज़ थोड़ा गड़बड़ कर रहे हैं, लेकिन यह कहने के लिए पर्याप्त है कि ये दो अभिव्यक्ति अधिक या कम समकक्ष हैं:
my_proc = :to_s.to_proc
my_proc = Proc.new {|obj| obj.to_s }
तो सवाल का जवाब "क्यों नहीं" टी &:*(2)
काम? "वह अभिव्यक्ति है जो निम्नानुसार है &
ऑपरेटर, :*(2)
, एक मान्य रूबी अभिव्यक्ति नहीं है। यह रूबी पार्सर के रूप में ज्यादा समझ में आता है "hello"(2)
.
वैसे भी, ऐसा करने का एक तरीका है जिसे आप "करने का प्रयास कर रहे हैं:
[1,2,3,4,5].map(&2.method(:*))
# => [2, 4, 6, 8, 10]
उपरोक्त कोड में, 2.method(:*)
एक संदर्भ देता है *
वस्तु की विधि 2
के रूप में तरीका वस्तु। विधि ऑब्जेक्ट्स प्रो ऑब्जेक्ट्स की तरह बहुत व्यवहार करते हैं, और वे जवाब देते हैं to_proc
। हालांकि, उपर्युक्त बिल्कुल बराबर नहीं है-यह करता है 2 * n
बजाय n * 2
(एक भेद जो कोई फर्क नहीं पड़ता है n
यह भी एक संख्यात्मक है) - और यह अब से अधिक संक्षिप्त या पठनीय नहीं है {|n| n * 2 }
, और शायद ही कभी परेशानी के लायक है।
उत्तर № 2 के लिए -1
Ampersand और वस्तु (और: विधि)
किसी ऑब्जेक्ट को किसी विधि को ब्लॉक के रूप में पास करने के लिए ऑपरेटर का उपयोग भी किया जा सकता है, जैसा कि निम्न उदाहरण में है:
arr = [ 1, 2, 3, 4, 5 ]
arr.map { |n| n.to_s }
arr.map &:to_s
उपरोक्त दोनों उदाहरणों का एक ही परिणाम है। दोनों में, नक्शा विधि एआर सरणी और एक ब्लॉक लेता है, फिर यह सरणी के प्रत्येक तत्व पर ब्लॉक चलाता है। ब्लॉक के अंदर कोड प्रत्येक तत्व पर to_s चलाता है, इसे पूर्णांक से स्ट्रिंग में परिवर्तित करता है। फिर, नक्शा विधि परिवर्तित वस्तुओं वाले एक नए सरणी देता है।
पहला उदाहरण आम है और व्यापक रूप से उपयोग किया जाता है। दूसरा उदाहरण पहली नज़र में थोड़ा सा गूढ़ दिख सकता है। चलो देखते हैं कि क्या हो रहा है:
रूबी में, कोलन के साथ prefixed आइटम (:) प्रतीक हैं। यदि आप सिंबल क्लास / डेटा प्रकार से परिचित नहीं हैं, तो मैं आपको Google को सुझाव देता हूं और जारी रखने से पहले कुछ लेख पढ़ता हूं। रुबी में सभी विधि नाम आंतरिक रूप से प्रतीकों के रूप में संग्रहीत हैं। एक कोलन के साथ एक विधि नाम उपसर्ग करके, हम विधि को एक प्रतीक में परिवर्तित नहीं कर रहे हैं, न ही हम विधि को बुला रहे हैं, हम बस विधि के संदर्भ (विधि का संदर्भ) का नाम पारित कर रहे हैं। उपर्युक्त उदाहरण में, हम पास कर रहे हैं: to_s, जो ampersand (&) ऑपरेटर के लिए to_s विधि का संदर्भ है, जो एक proc (हुड के नीचे to_proc को कॉल करके) बना देगा। Proc एक तर्क के रूप में एक मान लेता है, उस पर to_s कॉल करता है और एक स्ट्रिंग में परिवर्तित मान देता है।
हालांकि :नक्शा लूप चलाते समय to_s प्रतीक हमेशा समान होता है, यह प्रत्येक सरणी आइटम से संबंधित वर्ग की to_s विधि को संदर्भित करेगा। यदि हमने मैप विधि में [21, 4.453,: foobar,] जैसे सरणी को पास किया है, तो पहले आइटम पर फिक्सनम क्लास की to_s विधि लागू (कॉल) की जाएगी, फ्लोट क्लास की to_s विधि को लागू किया जाएगा दूसरी वस्तु और प्रतीक वर्ग की to_s विधि तीसरे आइटम पर लागू की जाएगी। यह समझ में आता है क्योंकि हम एम्पर्सेंड ऑपरेटर को वास्तविक to_s विधि को पार नहीं कर रहे हैं, बस इसका नाम।
नीचे एक ऐसी प्रक्रिया बनाने का एक उदाहरण है जो तर्क लेता है, उस पर एक विधि कहता है और विधि का परिणाम देता है।
p = :upcase.to_proc
p.call("foo bar")
Output:
=> "FOO BAR"
आइए देखें कि arr.map में क्या चल रहा है और: to_s
- मानचित्र के प्रत्येक पुनरावृत्ति पर, सरणी का एक आइटम (एक पूर्णांक) को पास किया जाता है और: to_s
- द:to_s प्रतीक (जो to_s विधि का संदर्भ है) को ऑपरेटर को पास किया जाता है, जो एक प्रोसेस बनाता है जो एक तर्क (एक सरणी आइटम) लेता है, तर्क पर to_s को कॉल करता है और स्ट्रिंग में परिवर्तित मान को वापस कर देता है;
- नक्शा विधि तारों "1", "2", "3", "4" और "5" युक्त एक नई सरणी देता है।