我需要将一些函数应用于值的映射.在最坏的情况下,函数大约是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)
您可以在前面添加一个&,然后使用它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"在数据库中存储等等.