我需要将一些函数应用于值的映射。 在最坏的情况下,函数大约是900函数,因此我将它们创建为数据库中的记录并立即将它们加载到地图中。这样我可以创建一个管理页面来管理所有转换公式...有一天......
现在我喜欢他们
conversion=%{"0":"Tools.Myfunc1/1","1":"Tools.Myfunc2/1",etc...}
然后我需要在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
答案 0 :(得分: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"
等存储在数据库中。
答案 1 :(得分:0)
Kernal.apply与String.to_atom结合使用对您有帮助吗?这将要求您在由apply
调用的模块中实现该功能。
apply(<Module Name>, <:string_converted_to_atom>, [<args>])