如何将字符串转换为Elixir中的函数

ram*_*ein 4 elixir

我需要将一些函数应用于值的映射.在最坏的情况下,函数大约是900函数,因此我将它们创建为数据库中的记录并立即将它们加载到地图中.这样我可以创建一个管理页面来管理所有转换公式...有一天......

现在我让他们这样

conversion=%{"0":"Tools.Myfunc1/1","1":"Tools.Myfunc2/1",etc...}
Run Code Online (Sandbox Code Playgroud)

然后我需要在map语句中应用/执行它们.

问题是它们是字符串,我得到这个错误

|>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
Run Code Online (Sandbox Code Playgroud)

Pat*_*ity 7

您可以在前面添加一个&,然后使用它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
Run Code Online (Sandbox Code Playgroud)

然后你可以这样做:

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!
Run Code Online (Sandbox Code Playgroud)

您可能希望将允许的函数限制为仅包含琐碎转换的特定模块,否则可能会带来一些安全风险.例如:

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

然后只是"upcase/1"在数据库中存储等等.