2011-01-27 13 views
22

हाल ही में मुझे पता चला कि tap का उपयोग नए चर के मानों को "ड्रिलि" करने के लिए किया जा सकता है; उदाहरण के लिए, बनाने और एक सरणी भरने, इस तरह के लिए:रूबी 'टैप' विधि - असाइनमेंट के अंदर

array = [].tap { |ary| ary << 5 if something } 

इस कोड में array अगर something truthy है 5 धक्का होगा; अन्यथा, array खाली रहेगा।

लेकिन मुझे समझ में नहीं क्यों इस कोड को क्रियान्वित करने के बाद करते हैं:

array = [].tap { |ary| ary += [5] if something } 

array खाली रहता है। क्या कोई मेरी मदद कर सकता है?

उत्तर

38

पहले मामले में array और ary एक ही ऑब्जेक्ट को इंगित करें। फिर आप << विधि का उपयोग करके उस ऑब्जेक्ट को म्यूटेट करते हैं। ऑब्जेक्ट कि array और ary बिंदु दोनों अब बदल गए हैं।

दूसरे मामले में array और ary दोनों एक ही सरणी पर इंगित करते हैं। अब आप ary वैरिएबल को पुनः असाइन करें, ताकि ary अब एक नई सरणी को इंगित कर सके। ary को पुन: असाइन करना हालांकि array पर कोई प्रभाव नहीं पड़ता है। एक परिवर्तनीय पुनर्विक्रय रूबी में अन्य चर को कभी प्रभावित नहीं करता है, भले ही वे पुन: असाइनमेंट से पहले एक ही ऑब्जेक्ट को इंगित करते हैं।

x = 23 
y = x 
y = 42 # Changes y, but not x 

संपादित करें:: एक और यथा-स्थान आप concat उपयोग कर सकते हैं करने के लिए एक सरणी संलग्न करने के लिए

दूसरे शब्दों array में अब भी वही कारण के लिए खाली कि x निम्न उदाहरण में 42 नहीं होगा विधि, जो += का उपयोग करने से भी तेज होना चाहिए।

+5

जोड़ें: 'a + = b' 'a = a + b' जैसा काम करता है - यहां सृजन का तथ्य एक नई वस्तु अधिक स्पष्ट है। – Nakilon

+1

@ नकिनॉन: ​​यह देखते हुए कि ओपी स्पष्ट रूप से असाइनमेंट के बारे में बात कर रहा था, मैंने माना कि वह हिस्सा उसके लिए स्पष्ट था। – sepp2k

+0

ठीक है, मुझे लगता है कि मैं समझ गया; यह असाइनमेंट ऑपरेशन का उपयोग नहीं करता है। जिस प्रभाव को मैं चाहता हूं उसे प्राप्त करने के लिए मुझे array = [].tap { |ary| [5].each{ |v| ary << 5 } } करना चाहिए --- आप अपनी टिप्पणियों में स्वरूपण कैसे जोड़ सकते हैं ?? – mdesantis

20

मैं इस एक सा पर विस्तार करना चाहते:

  1. प्रदान करती है [] को array, एक खाली सरणी:

    array = [].tap { |ary| ary << 5 if something } 
    

    यह क्या करता है (यह मानते हुए something-ish सच है)।

    array.object_id = 2152428060 
    
  2. ary के रूप में ब्लॉक करने के लिए [] गुजरता है। ary और array एक ही सरणी वस्तु को इंगित कर रहे हैं।

    array.object_id = 2152428060 
    ary.object_id = 2152428060 
    
  3. ary << 5 < < एक mutative विधि, जिसका अर्थ यह प्राप्त वस्तु को संशोधित करेगा है। यह ! को विधि कॉल में जोड़ने के मुहावरे के समान है, जिसका अर्थ है "इसे जगह में संशोधित करें!", जैसे .map बनाम .map! (हालांकि बैंग किसी विधि नाम में स्वयं का कोई आंतरिक अर्थ नहीं रखता है)।ary 5 डाला गया है, इसलिए ary = array = [5]

    array.object_id = 2152428060 
    ary.object_id = 2152428060 
    

हम array[5]

के बराबर दूसरे उदाहरण में किया जा रहा है के साथ समाप्त:

array = [].tap{ |ary| ary += [5] if something }  
  1. ही
  2. ही
  3. ary += 5+=ary = ary + 5 के लिए कम है, तो यह है, पहले संशोधन (+) और फिर काम (=) है इसी क्रम में। यह किसी ऑब्जेक्ट को जगह में संशोधित करने की उपस्थिति देता है, लेकिन वास्तव में यह नहीं करता है। यह एक पूरी तरह से नई वस्तु बनाता है।

    array.object_id = 2152428060 
    ary.object_id = 2152322420 
    

तो हम array मूल वस्तु, object_id=2152428060 के साथ एक खाली सरणी के रूप में, और ary, एक आइटम object_id = 2152322420 साथ युक्त 5 के साथ एक सरणी के साथ समाप्त। इसके बाद ary पर कुछ भी नहीं होता है। यह array के मूल असाइनमेंट के साथ असंगत है, जो पहले से ही हुआ है। array असाइन किए जाने के बाद ब्लॉक को निष्पादित करें टैप करें।

+1

यह एक बेहतरीन उत्तर और स्पष्टीकरण है। – tamouse

+1

ग्रेट स्पष्टीकरण -वेल किया गया। – Jurgen

संबंधित मुद्दे