2016-04-17 53 views
6

Genel olarak Elixir ve fonksiyonel programlama dillerinde oldukça yeniyim.Elixir - Dize adıyla modülde çağrı metodu

Elixir'de, Modül adı String olarak verildiğinde, Modüller'de belirli bir işlevi çağırmak istiyorum.

ben çok fazla ne istediğiniz, hangi çalışma aşağıdaki (çok kötü) kodu var etmek:

module_name = elem(elem(Code.eval_file("module.ex", __DIR__), 0), 1) 
apply(module_name, :helloWorld, []) 

Bu (Anladığım en azından gibi) ait (zaten derlenmiş) modülünü derler Geçerli dizinde module.ex. Modül adını (String olarak değil, aslında hangi veri tipini olduğunu bilmiyorum) iki tupldan çıkarıyorum ve üzerinde helloWorld metodunu çalıştırıyorum. Bu redefining module Balance gibi bir uyarı yazdırır

  1. :

    bu kodla iki sorun vardır. Bunun üretimde olmasını kesinlikle istemiyorum.

  2. AFAIK bu kod module.ex'u derler. Ancak, module.ex zaten derlenmiş ve yüklenmiş olduğundan, bunun olmasını istemez.

Bu modüllerde dosya adı yöntemlerini çağırmam gerekmiyor, modül adı da iyi olurdu. Ancak, dinamik olarak, ör. Komut satırında "Kitap" girilmesi, modülün mevcut olup olmadığını kontrol ettikten sonra, Book.helloWorld işlevini çağırmalıdır.

Teşekkürler.

cevap

9

Eh, istemek nerede yardımcı olur: Sorduğunuz dakika kendiniz çözeceksiniz. ;)

Sadece apply(String.to_existing_atom("Elixir.Module"), :helloWorld, []) kullanıyorsunuz. (belki de "Modül" ismine izin verilmez, Bilmiyor)

+2

Küçük bir not: Eğer mümkünse to_existing_atom kullanmalıdır. Atomlar toplanan çöp toplandı! –

+0

Teşekkürler! Atomların toplanmadığını bilmiyordum. Cevabımı düzenler. – lschuermann

1

Ayrıca, bir modülün adı bir atom olduğunu ve bu nedenle String.to_existing_atom yapmanın genellikle gerekli olmadığını unutmayın. (Liste aşağıda İksir List modülüdür)

apply(T,:first,[[1,2,3]]) 
#=> 1 

Veya bu örnekte: bu şekilde uygulamak Bu durumda

defmodule T do 
    def first([]), do: nil 
    def first([h|t]), do: h 
end 

basitçe yapabilirsiniz: Bu kodu düşünün

apply(List,:first,[[1,2,3]]) 
#=> 1 

Yani, modülün adını biliyorsanız, onu bir dizge olarak geçirmenin ve dizgiyi varolan bir atoma dönüştürmenin gerekli olmadığını söylemeliyim. Adını tırnak işaretleri olmadan kullanmanız yeterlidir.

+0

Evet, bu tamamen doğru.Ama benim durumumda, Modül-Adı dinamiğini yapma hedefiydi. Elbette, Modülün adını biliyorsanız, bu da işe yarayacaktır. – lschuermann

6

Modüllerinizi "Elixir" ile önek eklemeniz gerektiğini unutmayın.

defmodule Test do 
    def test(text) do 
    IO.puts("#{text}") 
    end 
end 

apply(String.to_existing_atom("Elixir.Test"), :test, ["test"]) 

baskılar "test" ve iadeler {: Tamam}