रूबी में विधि के नाम के साथ एक स्ट्रिंग से एक विधि कॉलिंग


157

मैं क्या वे के बारे में बात कर रहे हैं कैसे कर सकते हैं यहां , लेकिन रूबी में?

आप किसी ऑब्जेक्ट पर फ़ंक्शन कैसे करेंगे? और आप एक वैश्विक कार्य कैसे करेंगे (देखें पोस्ट में जेटी का जवाब देखें )

उदाहरण कोड:

event_name = "load"

def load()
  puts "load() function was executed."
end

def row_changed()
  puts "row_changed() function was executed."
end 

#something here to see that event_name = "load" and run load()

अद्यतन: आप वैश्विक तरीकों को कैसे प्राप्त करते हैं? या मेरे वैश्विक कार्य?

मैंने इस अतिरिक्त लाइन की कोशिश की

puts methods

और लोड और row_change जहां सूचीबद्ध नहीं हैं।

जवाबों:


232

किसी ऑब्जेक्ट पर सीधे फ़ंक्शन को कॉल करने के लिए

a = [2, 2, 3]
a.send("length")
# or
a.public_send("length")

जो उम्मीद के मुताबिक 3 रिटर्न देता है

या एक मॉड्यूल फ़ंक्शन के लिए

FileUtils.send('pwd')
# or
FileUtils.public_send(:pwd)

और एक स्थानीय रूप से परिभाषित विधि

def load()
    puts "load() function was executed."
end

send('load')
# or
public_send('load')

प्रलेखन:


3
+1 यह काम करता है। यह एक गूंगा हो सकता है ... लेकिन मैं कैसे रूबी स्रोत में भेज शब्द नहीं मिल सकता है - C: \ ruby ​​\ lib \ ruby ​​\ 1.8 \ fileutils.rb? सोचा था कि मैं वहाँ समारोह भेज दूंगा।
बडीजोई

1
मैं उत्सुक था कि यह हुड के नीचे क्या कर रहा था।
बडीजोई

यह ऑब्जेक्ट पर परिभाषित किया गया है - ruby-doc.org/core/classes/Object.html#M000332 मैंने ब्याज मूल्य के लिए एक यादृच्छिक फ़ंक्शन उठाया।
कॉलिन ग्रेविल सेप

1
दिलचस्प इसलिए कि इससे पहले कि मैं आपके उत्तर को दो बार पढ़ूँ, और पूरी तरह से इसे दबा दूं कि मैंने FileUtils.send ("लोड") चलाया और यह मेरे कार्य को चला गया। इसलिए अगर मैं इसे "ग्लोबल" में फ़ंक्शन बनाकर सही ढंग से समझता हूं तो क्या मैं रूट ऑब्जेक्ट पर तरीके जोड़ रहा हूं? या नहीं?
बडीजियो

12
स्रोत में सामान देखने के लिए आप पर अच्छा है! :)
कॉलिन ग्रेविल सेप

34

तीन तरीके: send/ call/ eval- और उनके बेंचमार्क

विशिष्ट मंगलाचरण (संदर्भ के लिए):

s= "hi man"
s.length #=> 6

का उपयोग करते हुए send

s.send(:length) #=> 6

का उपयोग करते हुए call

method_object = s.method(:length) 
p method_object.call #=> 6

का उपयोग करते हुए eval

eval "s.length" #=> 6

 

मानक

require "benchmark" 
test = "hi man" 
m = test.method(:length) 
n = 100000 
Benchmark.bmbm {|x| 
  x.report("call") { n.times { m.call } } 
  x.report("send") { n.times { test.send(:length) } } 
  x.report("eval") { n.times { eval "test.length" } } 
} 

... जैसा कि आप देख सकते हैं, किसी विधि को कॉल करने का तरीका, किसी विधि को कॉल करने का सबसे तेज़ गतिशील तरीका है, यह भी ध्यान दें कि eval का उपयोग करना कितना धीमा है।

#######################################
#####   The results
#######################################
#Rehearsal ----------------------------------------
#call   0.050000   0.020000   0.070000 (  0.077915)
#send   0.080000   0.000000   0.080000 (  0.086071)
#eval   0.360000   0.040000   0.400000 (  0.405647)
#------------------------------- total: 0.550000sec

#          user     system      total        real
#call   0.050000   0.020000   0.070000 (  0.072041)
#send   0.070000   0.000000   0.070000 (  0.077674)
#eval   0.370000   0.020000   0.390000 (  0.399442)

क्रेडिट इस ब्लॉग पोस्ट पर जाता है जो तीन तरीकों पर थोड़ा और विस्तृत होता है और यह भी दिखाता है कि तरीकों की मौजूदगी की जाँच कैसे करें।


मुझे बस यही पता चल रहा था, और मैंने कुछ देखा जो कवर नहीं किया गया था। अगर मैं करना चाहता था तो मैं क्या करूंगा Class.send("classVariable") = 5? वह एक त्रुटि फेंकता है। क्या उसके आसपास कोई रास्ता है? यही बात उपयोग करने के लिए सही हैClass.method("classVariable").call() = 5
thesecretmaster

यदि आप इस कॉल के साथ कुछ तर्क भेजना चाहते हैं, तो कुछ इस तरह का उपयोग करें ClassName.send ("method_name", arg1, arg2)
Aleem

सही समय का सही प्रतिनिधित्व करने के callलिए विधि ऑब्जेक्ट ( m.test.method(:length)) को तुरंत शामिल करने के लिए आपका बेंचमार्क नहीं होना चाहिए ? जब callआप का उपयोग कर रहे हैं संभावना है कि आप हर बार विधि ऑब्जेक्ट को तुरंत भेजेंगे।
जोशुआ पिंटर

ब्लॉग पोस्ट लिंक मृत है, btw।
जोशुआ पिंटर

33

इसे इस्तेमाल करो:

> a = "my_string"
> meth = a.method("size")
> meth.call() # call the size method
=> 9

सरल, सही?

के रूप में वैश्विक , मुझे लगता है कि जिस तरह से रूबी का उपयोग कर इसे खोज करने के लिए किया जाएगा methodsविधि।


meth = a.method? क्या यह फ़ंक्शन पहले से ही कॉल नहीं कर रहा है? क्या होगा अगर विधि कुछ लौटाती है?
user1735921 7

FYI करें जब विधि मौजूद नहीं है: "my_string".method('blah') #=> NameError: undefined method वर्ग के लिए blah 'String'
जोशुआ पिंटर

3

व्यक्तिगत रूप से मैं एक हैश को संदर्भों को व्यवस्थित करने के लिए सेटअप करता हूं और फिर स्ट्रिंग को एक सूचकांक के रूप में उपयोग करता है। आप इसके साथ फ़ंक्शन संदर्भ को पैरामीटर कहते हैं। यह गलत स्ट्रिंग को कुछ कॉल करने की अनुमति नहीं देने का लाभ है जिसे आप कॉल नहीं करना चाहते हैं। दूसरा तरीका मूल रूप से हैeval से स्ट्रिंग है। यह मत करो।

PS आलसी मत बनो और वास्तव में किसी चीज़ से जोड़ने के बजाय अपने पूरे प्रश्न को टाइप करो।


माफ़ करना। मैं कुछ शब्दों की नकल करूंगा और इसे रूबी को विशिष्ट बनाने के लिए अनुवाद करूंगा। +1
बुडीजॉए सेप
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.