erlang metaprogramming elixir

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])