2012-11-05 6 views
27

मुझे पता है कि वास्तव में क्या एक विधि नाम अमृत में है करना चाहते हैं:मॉड्यूल और विधि नाम दोनों निर्दिष्ट करके, Elixir में गतिशील रूप से एक विधि को कैसे कॉल करें?

array = [1,2,3] 
module_name = :lists 
method_name = :nth     # this not working 
module_name.method_name(1, array) # error, undef function lists.method_name/2 
module_name.nth(1, array)   # returns 1, module_name is OK. It's an atom 

लेकिन मैं erlang में लगभग एक ही बात कर सकते हैं:

A = [1,2,3]. 
X = lists. 
Y = nth. 
X:Y(1,A). # returns 1 

मैं कैसे अमृत में ऐसा कर सकते हैं?

उत्तर

39

आप apply/3 का उपयोग कर सकते हैं जो :erlang.apply/3 के आसपास सिर्फ एक रैपर है। यह बस invokes the given function from the module with an array of arguments. चूंकि आप मॉड्यूल और फ़ंक्शन नाम के रूप में तर्क पारित कर रहे हैं, इसलिए आप चर का उपयोग कर सकते हैं।

apply(:lists, :nth, [1, [1,2,3]]) 
apply(module_name, method_name, [1, array]) 

आप के बारे में कैसे अमृत समारोह कॉल (और बाकी सब कुछ) आप quote और unquote पर एक नज़र रखना चाहिए संभालती अधिक समझने के लिए चाहते हैं।

contents = quote do: unquote(module_name).unquote(method_name)(1, unquote(array)) 

जो फ़ंक्शन कॉल का होमियोइकोनिक प्रतिनिधित्व देता है।

{{:.,0,[:lists,:nth]},0,[1,[1,2,3]]} 

आप के साथ Code.eval_quoted/3

{value, binding} = Code.eval_quoted(contents) 

संपादित उद्धृत समारोह कॉल unquote कर सकते हैं: यहाँ एक वर के साथ Enum.fetch का उपयोग कर एक उदाहरण है।

quoted_fetch = quote do: Enum.fetch([1,2,3], var!(item));    
{value, binding} = Code.eval_quoted(quoted_fetch, [item: 2]) 
+0

अच्छा। तो विधि का नाम एक परमाणु है। अब मुझे लगता है कि यह सिर्फ वाक्यविन्यास है जो हमें elixir में 'module.method' लिखने की अनुमति नहीं देता है, है ना? – halfelf

+1

मेरा मानना ​​है कि आप सही हैं। मुझे लगता है कि इस काम को करने का एकमात्र तरीका मॉड्यूल फ़ंक्शंस को कॉल करते समय परमाणुओं का उपयोग करने के लिए वाक्यविन्यास को बदलना होगा (यानी 'सूचियां: nth')। मैं बस इस तरह के मामलों में आवेदन का उपयोग करना चाहूंगा। – lastcanal

+0

धन्यवाद। यह जवाब बहुत उपयोगी है। – halfelf

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