Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to convert a string to a function in Elixir

Tags:

elixir

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
like image 373
ramstein Avatar asked Mar 14 '23 10:03

ramstein


1 Answers

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.

like image 153
Patrick Oscity Avatar answered Mar 20 '23 11:03

Patrick Oscity