erlang - ¿Cómo llamar dinámicamente un método en Elixir, especificando el nombre del módulo y el método?
metaprogramming (1)
Me gustaría saber exactamente el nombre de un método en el elixir:
array = [1,2,3]
module_name = :lists
method_name = :nth # this not working
module_name.method_name(1, array) # error, undef function lists.method_name/2
module_name.nth(1, array) # returns 1, module_name is OK. It''s an atom
Pero puedo hacer casi lo mismo en erlang:
A = [1,2,3].
X = lists.
Y = nth.
X:Y(1,A). # returns 1
¿Cómo puedo hacer esto en el elixir?
Puede usar apply/3
que es solo un contenedor :erlang.apply/3
. Simplemente invoca la function
dada del module
con una matriz de arguments
. Como está pasando argumentos como el módulo y los nombres de funciones, puede usar variables.
apply(:lists, :nth, [1, [1,2,3]])
apply(module_name, method_name, [1, array])
Si desea comprender más acerca de cómo elixir maneja las llamadas a funciones (y todo lo demás), debe consultar las quote
y las unquote
.
contents = quote do: unquote(module_name).unquote(method_name)(1, unquote(array))
que devuelve la representación homoicónica de la llamada a la función.
{{:.,0,[:lists,:nth]},0,[1,[1,2,3]]}
Puede unquote
la cita de la llamada de función citada con Code.eval_quoted/3
{value, binding} = Code.eval_quoted(contents)
Editar: aquí hay un ejemplo que usa Enum.fetch junto con una var.
quoted_fetch = quote do: Enum.fetch([1,2,3], var!(item));
{value, binding} = Code.eval_quoted(quoted_fetch, [item: 2])