क्या तरीकों के अंदर तरीके होना संभव है?


89

मेरे पास एक विधि एक विधि है। आंतरिक विधि एक चर लूप पर निर्भर करती है जिसे चलाया जा रहा है। क्या यह एक बुरा विचार है?


2
क्या आप कोड नमूना साझा कर सकते हैं या कम से कम एक तार्किक समकक्ष जो आप करने की कोशिश कर रहे हैं।
एरोन स्क्रैग्स

जवाबों:


165

अद्यतन: चूंकि यह उत्तर हाल ही में कुछ ब्याज पाने के लिए प्रतीत होता है, इसलिए मैं यह इंगित करना चाहता था कि रूबी मुद्दे पर चर्चा की जा सकती है कि यहां चर्चा की गई विशेषता को हटाने के लिए, अर्थात् एक विधि निकाय के अंदर विधि परिभाषाओं को मना करने के लिए


नहीं, रूबी के पास नेस्टेड तरीके नहीं हैं।

आप ऐसा कुछ कर सकते हैं:

class Test1
  def meth1
    def meth2
      puts "Yay"
    end
    meth2
  end
end

Test1.new.meth1

लेकिन यह एक नेस्टेड विधि नहीं है। मैं दोहराता हूं: रूबी के पास नेस्टेड तरीके नहीं हैं

यह क्या है, एक गतिशील विधि परिभाषा है। जब आप चलाते हैं meth1, तो निकाय meth1निष्पादित किया जाएगा। शरीर सिर्फ नाम की एक विधि को परिभाषित करने के लिए होता है meth2, यही कारण है कि meth1एक बार चलने के बाद, आप कॉल कर सकते हैं meth2

लेकिन meth2परिभाषित कहां है ? खैर, यह स्पष्ट रूप से एक नेस्टेड विधि के रूप में परिभाषित नहीं है, क्योंकि रूबी में कोई नेस्टेड तरीके नहीं हैं । इसे एक उदाहरण विधि के रूप में परिभाषित किया गया है Test1:

Test1.new.meth2
# Yay

इसके अलावा, यह स्पष्ट रूप से हर बार आपके द्वारा चलाए जाने पर पुनर्परिभाषित किया जाएगा meth1:

Test1.new.meth1
# Yay

Test1.new.meth1
# test1.rb:3: warning: method redefined; discarding old meth2
# test1.rb:3: warning: previous definition of meth2 was here
# Yay

संक्षेप में: नहीं, रूबी नेस्टेड तरीकों का समर्थन नहीं करता है

ध्यान दें कि रूबी में, विधि निकायों को बंद नहीं किया जा सकता है, केवल ब्लॉक निकाय कर सकते हैं। यह बहुत ज्यादा नेस्टेड तरीकों के लिए प्रमुख उपयोग के मामले को समाप्त करता है, भले ही रूबी नेस्टेड तरीकों का समर्थन किया हो, आप नेस्टेड विधि में बाहरी विधि के चर का उपयोग नहीं कर सकते।


अद्यतन किया गया: बाद के चरण में, फिर, इस वाक्यविन्यास को रूबी में नेस्टेड विधियों को जोड़ने के लिए फिर से उपयोग किया जा सकता है, जो मेरे द्वारा वर्णित तरीके का व्यवहार करेगा: उन्हें उनकी युक्त विधि, अर्थात अदृश्य और दुर्गम उनके युक्त विधि के बाहर स्कोप किया जाएगा तन। और संभवत:, उनके पास अपने विधि के शाब्दिक दायरे तक पहुंच होगी। हालाँकि, यदि आप ऊपर चर्चा से जुड़े लिंक को पढ़ते हैं, तो आप निरीक्षण कर सकते हैं कि मेत्ज़ नेस्टेड विधियों के विरुद्ध है (लेकिन अभी भी नेस्टेड विधि परिभाषाओं को हटाने के लिए)।


6
हालाँकि, आप यह भी दिखा सकते हैं, कि DRYness के लिए विधि में क्लोजर लैम्बडा कैसे बनाते हैं, या रिकर्सन चलाने के लिए।
17

119
मुझे लग रहा है कि रूबी के पास नेस्टेड तरीके नहीं होंगे।
मार्क थॉमस

16
@ मर्क थॉमस: क्या मैं इस बात का उल्लेख करना भूल गया कि रूबी ने घोंसले के तरीकों से घृणा नहीं की है? :-) गंभीरता से: समय मैं इस जवाब लिखा में, वहाँ पहले से ही तीन उत्तर, हर एक जिनमें से एक ने दावा किया रूबी कि थे करता नेस्टेड तरीकों की है। उन जवाबों में से कुछ भी blatantly गलत होने के बावजूद upvotes था। एक को भी ओपी ने गलत मानने के बावजूद दोबारा स्वीकार कर लिया। कोड स्निपेट जो उत्तर देता है वह यह साबित करने के लिए उपयोग करता है कि रूबी नेस्टेड तरीकों का समर्थन करता है, वास्तव में विपरीत साबित होता है, लेकिन स्पष्ट रूप से न तो upvoters और न ही ओपी वास्तव में जांच करने के लिए परेशान है। इसलिए, मैंने हर गलत के लिए एक सही जवाब दिया। :-)
जोर्ग डब्ल्यू मित्तग

10
जब आपको पता चलता है कि ये सभी कर्नेल को निर्देश हैं जो तालिकाओं को संशोधित करते हैं और ये तरीके और वर्ग और मॉड्यूल सभी तालिकाओं में प्रविष्टियां हैं और वास्तव में वास्तविक नहीं हैं, तो आप नियो की तरह हो जाते हैं जब वह देखता है कि मैट्रिक्स कैसा दिखता है। तब आप वास्तव में दार्शनिक बन सकते हैं और कह सकते हैं कि नेस्टेड विधियों के अलावा, कोई विधियाँ भी नहीं हैं। एजेंट भी नहीं हैं। वे मैट्रिक्स में प्रोग्राम हैं। यहां तक ​​कि रसदार स्टेक जो आप खा रहे हैं, वह केवल एक तालिका में एक प्रविष्टि है।
mydoghasworms

3
कोई विधियाँ नहीं हैं, आपका कोड द मेट्रिक्स में एक सिमुलेशन है
bbozo

13

वास्तव में यह संभव है। इसके लिए आप procs / lambda का उपयोग कर सकते हैं।

def test(value)
  inner = ->() {
    value * value
  }
  inner.call()
end

2
आप गलत नहीं हैं, लेकिन आपका जवाब नेस्टेड तरीकों को प्राप्त करने के लिए एक समाधान के रूप में लिया गया है। जब वास्तव में आप केवल प्रॉक्स का उपयोग कर रहे हैं जो विधियाँ नहीं हैं। यह "नेस्टेड तरीकों" को हल करने के दावे के बाहर एक अच्छा जवाब है
ब्रैंडन बक

5

नहीं, नहीं, रूबी के पास नेस्टेड तरीके हैं। इसे देखो:

def outer_method(arg)
    outer_variable = "y"
    inner_method = lambda {
      puts arg
      puts outer_variable
    }
    inner_method[]
end

outer_method "x" # prints "x", "y"

9
inner_method एक विधि नहीं है, यह एक फंक्शन / लैम्ब्डा / proc है। किसी वर्ग का कोई संबद्ध उदाहरण नहीं है इसलिए यह एक विधि नहीं है।
सामी संहिता २५'१३

2

आप ऐसा कुछ कर सकते हैं

module Methods
  define_method :outer do 
    outer_var = 1
    define_method :inner do
      puts "defining inner"
      inner_var = outer_var +1
    end
    outer_var
  end
  extend self
end

Methods.outer 
#=> defining inner
#=> 1
Methods.inner 
#=> 2

यह तब उपयोगी होता है जब आप डीएसएल लिखने जैसे काम कर रहे होते हैं जिसके लिए तरीकों के बीच गुंजाइश की आवश्यकता होती है। लेकिन अन्यथा, आप कुछ और करने से बहुत बेहतर हैं, क्योंकि जैसा कि अन्य उत्तर में कहा गया है, innerजब भी outerलागू किया जाता है , तो इसे फिर से परिभाषित किया जाता है। यदि आप इस व्यवहार को चाहते हैं, और आप कभी-कभी कर सकते हैं, तो इसे प्राप्त करने का यह एक अच्छा तरीका है।


2

माणिक हैक को भ्रमित करने के लिए रूबी तरीका नकली है जो कुछ उपयोगकर्ताओं को सोच रहा होगा "बकवास में यह कैसे काम करता है?", जबकि कम जिज्ञासु बस चीज़ का उपयोग करने के लिए आवश्यक वाक्यविन्यास को याद करेगा। यदि आपने कभी रेक या रेल का उपयोग किया है, तो आपने इस तरह की चीज देखी है।

यहाँ ऐसी हैक है:

def mlet(name,func)
  my_class = (Class.new do
                def initialize(name,func)
                  @name=name
                  @func=func
                end
                def method_missing(methname, *args)
                  puts "method_missing called on #{methname}"
                  if methname == @name
                    puts "Calling function #{@func}"
                    @func.call(*args)
                  else
                    raise NoMethodError.new "Undefined method `#{methname}' in mlet"
                  end
                end
              end)
  yield my_class.new(name,func)
end

वह जो करता है वह एक शीर्ष-स्तरीय पद्धति को परिभाषित करता है जो एक वर्ग बनाता है और इसे एक ब्लॉक में भेजता है। वर्ग method_missingयह दिखावा करने के लिए उपयोग करता है कि यह आपके द्वारा चुने गए नाम के साथ एक विधि है। यह आपके द्वारा प्रदान किए गए लैम्ब्डा को कॉल करके विधि को "लागू करता है"। ऑब्जेक्ट को एक-अक्षर के नाम के साथ नाम देकर, आप अतिरिक्त टाइपिंग की मात्रा को कम कर सकते हैं, जिसके लिए इसकी आवश्यकता होती है (जो एक ही चीज़ है जो रेल अपने में करता है schema.rb)। mletआम लिस्प फॉर्म के नाम पर रखा गया है flet, जहां f"फ़ंक्शन" mके लिए खड़ा है, "विधि" के लिए खड़ा है।

आप इसे इस तरह उपयोग करते हैं:

def outer
   mlet :inner, ->(x) { x*2 } do |c|
     c.inner 12
   end
end

एक समान गर्भनिरोधक बनाना संभव है जो कई आंतरिक कार्यों को अतिरिक्त घोंसले के शिकार के बिना परिभाषित करने की अनुमति देता है, लेकिन इसके लिए आपको उस प्रकार की एक भी बदसूरत हैक की आवश्यकता होती है जो आपको रेक या आरस्पेक के कार्यान्वयन में मिल सकती है। यह पता लगाना कि Rspec के let!कार्यों से आपको इस तरह के भयानक घृणा पैदा करने में सक्षम होने के लिए एक लंबा रास्ता मिल जाएगा।


-3

:-D

रूबी के पास नेस्टेड तरीके हैं, केवल वे नहीं करते हैं जो आप उनसे उम्मीद करेंगे

1.9.3p484 :001 > def kme; 'kme'; def foo; 'foo'; end; end              
 => nil 
1.9.3p484 :003 >   self.methods.include? :kme
 => true 
1.9.3p484 :004 > self.methods.include? :foo
 => false 
1.9.3p484 :005 > kme
 => nil 
1.9.3p484 :006 > self.methods.include? :foo
 => true 
1.9.3p484 :007 > foo
 => "foo" 

4
यह नेस्टेड विधि नहीं है ... स्पष्ट समझ के लिए Jörg W Mittag का उत्तर देखें।
हार्दिक
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.