2016-04-17 70 views
6

我對Elixir和函數式編程語言相當陌生。Elixir - 通過字符串名稱在模塊上調用方法

在花好月圓,我想打電話模塊中的一個特定的功能,所指定的模塊名稱字符串。

我有以下(非常糟糕)代碼的工作,這幾乎是我想要做什麼:

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

這(至少據我所知)編譯的(已編譯)模塊module.ex在當前目錄中。我從兩個元組中提取模塊名稱(不是字符串,不知道它實際上是什麼數據類型),並在其上運行方法helloWorld

有兩個問題與此代碼:

  1. 它打印像redefining module Balance警告。我當然不希望這種情況發生在生產中。

  2. AFAIK這個代碼編譯module.ex。但是,由於module.ex已經被編譯和加載,所以不希望發生這種情況。

我不需要通過文件名來調用這些模塊的方法,模塊名也可以。但它必須通過動態的,例如。在命令行輸入「Book」應在檢查模塊是否存在後調用功能Book.helloWorld

謝謝。

回答

9

那麼,這就是要求幫助:你會問你自己一個問題。 ;)

現在就使用apply(String.to_existing_atom("Elixir.Module"), :helloWorld, [])。 (可能命名爲「模塊」是不允許的,不知道)

+2

小記:你應該使用to_existing_atom只要有可能。原子沒有收集垃圾! –

+0

謝謝!我不知道原子不是垃圾收集。將編輯我的答案。 – lschuermann

1

還要注意的是模塊的名稱是這樣做通常不需要String.to_existing_atom原子。考慮以下代碼:

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

在這種情況下,你可以簡單地就以這種方式適用於:

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

還是這個例子中(下面列出的是藥劑List模塊):

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

我的意思是說,如果您知道模塊的名稱,則不需要將它作爲字符串傳遞,然後將字符串轉換爲現有的原子。只需使用不帶引號的名稱即可。

+0

是的,這是完全正確的。但就我而言,這是製作模塊名稱動態的目標。當然,如果你知道模塊的名字,那也可以。 – lschuermann

6

請注意,您總是需要在模塊前添加「Elixir」。

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

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

打印 「測試」 返回{:OK】

相關問題