How to set first-class module dynamically?

I have a logic like this. All the modules have the same patterns in their names(Foo.Module_[NUMERIC]). Can I set the module into f more simply like: f = Foo.Module_#{id}; f.get() ?

id = 2

f = case id do
  "1" => Foo.Module_1
  "2" => Foo.Module_2
  "3" => Foo.Module_3

defmodule Foo.Module_1 do
  def get(), do: SOME-LOGICS-HERE
defmodule Foo.Module_2 do
  def get(), do: SOME-LOGICS-HERE
defmodule Foo.Module_3 do
  def get(), do: SOME-LOGICS-HERE
1 Like

That’s a somewhat unorthodox approach, but it’s possible:

# Will raise if there's an attempt to use a number
# that doesn't have a corresponding module
mod = String.to_existing_atom("Elixir.Foo.Module_#{num}")

# Just call afterwards

The use of the String.to_existing_atom/1 is necessary because string to atom conversion isn’t safe in Erlang/Elixir, as atoms are not garbage collected, and filling up the atoms table is one of the ways to bring down the BEAM. Since the modules should be defined in the first place, the atoms that reference their names will already exist.

Hope it helps you :smiley:


It worked perfectly as I expected.
Thank you.

1 Like