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:
case statments. example.
case x do
"foo" -> foo
"bar" -> bar
end
use macros that transform the string into function.
create a map with that maps a string to the function to call.
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
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!
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