Reflection

Hi

What are the strategies for doing reflection in Elixir. In other words I want to map a runtime value, typically from a string, to a function call. I can think of a few ways:

  1. case statments. example.
case x do 
  "foo" -> foo
   "bar" -> bar
end
  1. use macros that transform the string into function.

  2. create a map with that maps a string to the function to call.

Any other ways?

I’d go for option 1 or 3, but I do not understand what you mean by 2.

If that runtime value is a string and does directly match to a function call, you could use String.to_existing_atom/1 and Kernel.apply/3. Perhaps you have to fetch a module from thin air then :wink:

But in general, I really think that whitelisting certain values via a case (if known at compile time) or a map (if dynamic) is the most secure way to go. But be prepared for the worst in the dynamic case!

1 Like

If it’s just intended to be a dynamic mapping to functions in a specific module, one could make it fairly safe by just checking that a matching exported (public) function exists, with the correct arity (assuming 0 in this case, for no args):

fun = String.to_existing_atom(x)
case function_exported?(SomeModule, fun, 0) do
  true -> apply(SomeModule, fun, [])
  false -> {:error, :undefined_function}
end
5 Likes