Elixir - Call method on module by String-name

Here is a simple explanation:

Assuming that you have a module like this:

defmodule MyNamespace.Printer do
  def print_hello(name) do
    IO.puts("Hello, #{name}!")
  end
end

Then you have a string that hold the module name that you can pass around in your application like this:

module_name = "Elixir.MyNamespace.Printer"

Whenever you receive the string module_name, you can instantiate a module and call functions on the module like this:

module = String.to_existing_atom(module_name)
module.print_hello("John")

It will print:

Hello, John!

Another way to dynamically call the function MyNamespace.Printer.print_hello/1 is:

print_hello_func = &module.print_hello/1
print_hello_func.("Jane")

It will print:

Hello, Jane!

Or if you want to have both module_name as atom and function_name as atom, and pass them around to be executed somewhere, you can write something like this:

a_module_name = :"Elixir.MyNamespace.Printer"
a_function_name = :print_hello

Then whenever you have a_module_name and a_function_name as atoms, you can call like this:

apply(a_module_name, a_function_name, ["Jackie"])

It will print

Hello, Jackie!

Of course you can pass module_name and function_name as strings and convert them to atoms later. Or you can pass module name as atom and function as a reference to function.


Well, thats where asking helps: You'll figure it out yourself the minute you ask. ;)

Just using apply(String.to_existing_atom("Elixir.Module"), :helloWorld, []) now. (maybe the name "Module" isn't allowed, don't know)


Note that you always need to prefix your modules with "Elixir."

defmodule Test do
  def test(text) do
    IO.puts("#{text}")
  end
end

apply(String.to_existing_atom("Elixir.Test"), :test, ["test"])

prints "test" and returns {:ok}