मेरे पास एक विधि एक विधि है। आंतरिक विधि एक चर लूप पर निर्भर करती है जिसे चलाया जा रहा है। क्या यह एक बुरा विचार है?
जवाबों:
अद्यतन: चूंकि यह उत्तर हाल ही में कुछ ब्याज पाने के लिए प्रतीत होता है, इसलिए मैं यह इंगित करना चाहता था कि रूबी मुद्दे पर चर्चा की जा सकती है कि यहां चर्चा की गई विशेषता को हटाने के लिए, अर्थात् एक विधि निकाय के अंदर विधि परिभाषाओं को मना करने के लिए ।
नहीं, रूबी के पास नेस्टेड तरीके नहीं हैं।
आप ऐसा कुछ कर सकते हैं:
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
संक्षेप में: नहीं, रूबी नेस्टेड तरीकों का समर्थन नहीं करता है ।
ध्यान दें कि रूबी में, विधि निकायों को बंद नहीं किया जा सकता है, केवल ब्लॉक निकाय कर सकते हैं। यह बहुत ज्यादा नेस्टेड तरीकों के लिए प्रमुख उपयोग के मामले को समाप्त करता है, भले ही रूबी नेस्टेड तरीकों का समर्थन किया हो, आप नेस्टेड विधि में बाहरी विधि के चर का उपयोग नहीं कर सकते।
अद्यतन किया गया: बाद के चरण में, फिर, इस वाक्यविन्यास को रूबी में नेस्टेड विधियों को जोड़ने के लिए फिर से उपयोग किया जा सकता है, जो मेरे द्वारा वर्णित तरीके का व्यवहार करेगा: उन्हें उनकी युक्त विधि, अर्थात अदृश्य और दुर्गम उनके युक्त विधि के बाहर स्कोप किया जाएगा तन। और संभवत:, उनके पास अपने विधि के शाब्दिक दायरे तक पहुंच होगी। हालाँकि, यदि आप ऊपर चर्चा से जुड़े लिंक को पढ़ते हैं, तो आप निरीक्षण कर सकते हैं कि मेत्ज़ नेस्टेड विधियों के विरुद्ध है (लेकिन अभी भी नेस्टेड विधि परिभाषाओं को हटाने के लिए)।
वास्तव में यह संभव है। इसके लिए आप procs / lambda का उपयोग कर सकते हैं।
def test(value)
inner = ->() {
value * value
}
inner.call()
end
नहीं, नहीं, रूबी के पास नेस्टेड तरीके हैं। इसे देखो:
def outer_method(arg)
outer_variable = "y"
inner_method = lambda {
puts arg
puts outer_variable
}
inner_method[]
end
outer_method "x" # prints "x", "y"
आप ऐसा कुछ कर सकते हैं
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
लागू किया जाता है , तो इसे फिर से परिभाषित किया जाता है। यदि आप इस व्यवहार को चाहते हैं, और आप कभी-कभी कर सकते हैं, तो इसे प्राप्त करने का यह एक अच्छा तरीका है।
माणिक हैक को भ्रमित करने के लिए रूबी तरीका नकली है जो कुछ उपयोगकर्ताओं को सोच रहा होगा "बकवास में यह कैसे काम करता है?", जबकि कम जिज्ञासु बस चीज़ का उपयोग करने के लिए आवश्यक वाक्यविन्यास को याद करेगा। यदि आपने कभी रेक या रेल का उपयोग किया है, तो आपने इस तरह की चीज देखी है।
यहाँ ऐसी हैक है:
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!
कार्यों से आपको इस तरह के भयानक घृणा पैदा करने में सक्षम होने के लिए एक लंबा रास्ता मिल जाएगा।
:-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"