2016-02-02 43 views
3

我需要將一些函數應用於值映射。 在最糟糕的情況下,函數大約有900個函數,所以我將它們創建爲數據庫中的記錄並一次將它們加載到地圖。這樣我可以創建管理頁面來管理所有的轉換公式......有一天.. 。如何將字符串轉換爲Elixir中的函數

現在我讓他們這樣

conversion=%{"0":"Tools.Myfunc1/1","1":"Tools.Myfunc2/1",etc...} 

然後我需要申請/在地圖聲明執行它們。

的問題是,他們是爲字符串,我得到這個錯誤

|>Stream.zip(conversion) |>Enum.map(fn {rawValue, formula} -> convertUsing(rawValue,formula) end) 預期的功能,得到了「myModule.Myfunc/1」

def convertUsing(value,formula) do 
     {h,form}=formula 
      value 
      |>ieee 
      |>form.() 
    end 
+0

他們都擁有1或可以改變?另外,它看起來像當你在'convertUsing'中調用函數時,你期望的arity爲0,這意味着沒有參數。 –

+0

永遠都是1。如果我只是在ConvertUsing中傳遞一個&myFunc1/1,它就會起作用 – ramstein

回答

6

你可以在前面加上一個&,然後用Code.eval_string/1來評估字符串的內容。這會給你想要的拍攝功能:

defmodule Conversion do 
    def convert_using(value, conversions) do 
    conversions 
    |> Enum.map(&string_to_fun/1) 
    |> Enum.reduce(value, &apply(&1, [&2])) 
    end 

    defp string_to_fun(str) do 
    {fun, _} = Code.eval_string("&#{str}") 
    fun 
    end 
end 

然後,你可以這樣做:

defmodule Tools do 
    def piratize(str), do: "#{str} arr!" 
    def upcase(str), do: String.upcase(str) 
end 

"Hello, world!" 
|> Conversion.convert_using(["Tools.piratize/1", "Tools.upcase/1"]) 
|> IO.puts 

# HELLO, WORLD! ARR! 

您可能要限制所允許的功能僅包含瑣碎轉換或使某一模塊,否則你可能會帶來一些安全風險。例如:

defp string_to_fun(str) do 
    {fun, _} = Code.eval_string("&Tools.#{str}") 
    fun 
end 

然後只是在數據庫中存儲"upcase/1"等。

相關問題