I need to apply some functions to a map of values. The functions are around 900 function in the worst case so i created them as records in a database and load them at once to a map.This way i may create an admin page to manage all the conversion formulas ... one day...
Now I have them like this
conversion=%{"0":"Tools.Myfunc1/1","1":"Tools.Myfunc2/1",etc...}
then I need to apply/execute them in a map statement.
The problem is that they are as strings and i get this error
|>Stream.zip(conversion)
|>Enum.map( fn {rawValue, formula} -> convertUsing(rawValue,formula) end)
expected a function, got "myModule.Myfunc/1"
def convertUsing(value,formula) do
{h,form}=formula
value
|>ieee
|>form.()
end
You could prepend a &
and then use Code.eval_string/1
to evaluate the contents of the string. This will give you the desired captured function:
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
Then you can do:
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!
You might want to restrict the allowed functions to a certain module that contains only trivial conversions or so, otherwise you might introduce some security risk. For example:
defp string_to_fun(str) do
{fun, _} = Code.eval_string("&Tools.#{str}")
fun
end
And then just store "upcase/1"
and so on in the database.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With