Я нашел Kernel.apply/3
, который позволяет динамически вызывать открытый метод в модуле, указав метод как атом, например. result = apply(__MODULE__, :my_method, [arg])
переводится на result = my_method(arg)
Что меня озадачивает - это способ вызова частного метода; Данный код выглядит следующим образом:
defmodule MyModule do
def do_priv(atom, args) when is_list(args) do
apply(__MODULE__, atom, args)
end
# (change defp => def, and this all works)
defp something_private(arg), do: arg #or whatever
end
Я ожидал бы, что MyModule.do_priv(:something_private, [1])
допустимо, так как это вызов частного метода изнутри модуля. Я могу оценить, что под капотом Elixir использует Erlang apply/3, и поэтому этот подход, вероятно, не приведет нас туда.
Я также пробовал использовать метод Code.eval_quoted/3
, но он даже не способен вызывать жесткокодированный частный метод (и, следовательно, время, затрачиваемое на создание AST вручную, вместо использования quote do
как ниже - хотя это вариант, если кто-то видит, как это сделать):
defmodule MyModule do
def do_priv_static do
something_private(1) #this works just fine
end
def do_priv_dynamic do
code = quote do
something_private(1)
end
Code.eval_quoted(code, [], __ENV__) #nope. fails
end
defp something_private(arg), do: arg #or whatever
end
Опять же, он получает доступ к частной функции изнутри содержащего модуля, поэтому я ожидаю, что это будет допустимо. Возможно, что я просто не понимаю параметр __ENV__
для eval_quoted
Единственное рабочее решение прямо сейчас меняет defp
на def
, что является прекрасным решением для моего личного кода; но поскольку я пишу код, который поддерживает других программистов, которые заботятся, я бы хотел найти решение.
Я открыт для других подходов, но лично я не понимаю, как это сделать.