elixir

Convert Module name to String and back to module


If we have a module name like this:

 Module.V1.CountryTest

I can convert it to String like this:

   Module.V1.CountryTest |> to_string

Now there are some interesting results I am getting on iex

   module = Module.V1.CountryTest |> to_string
         "Elixir.Module.V1.CountryTest"
   iex(2)> replace = Regex.replace(~r/Test/, module, "")
        "Elixir.Module.V1.Country"
   iex(3)> replace |> String.to_atom
         Module.V1.Country

So if I remove Test. And convert it back to atom. It will give me back the module name. But If I replace or remove anything else from the module name it gives me this output:

   some = Regex.replace(~r/Country/, replace, "")
     "Elixir.Module.V1."
   iex(5)> some |> String.to_atom
     :"Elixir.Module.V1."

Can anybody please explain this behavior? And why it wont allow any other parts to change or replace. Meaning giving me back the output like this

 Module.V1.Country

I mean if its possible.

Thanks.


Solution

  • Elixir module names are just atoms prefixed with "Elixir.". Elixir prints atoms which start with "Elixir." and contain a valid Elixir module name after that differently than other atoms:

    iex(1)> :"Elixir.Foo"
    Foo
    iex(2)> :"Elixir.F-o"
    :"Elixir.F-o"
    

    When you replace Test, the rest of the value is a valid Elixir module name, but when you replace Country as well, you end up with a . at the end which is not a valid module name. If you remove the dot too, you'll get what you want:

    iex(3)> Module.V1.Country |> to_string |> String.replace(~r/Country/, "") |> String.to_atom
    :"Elixir.Module.V1."
    iex(4)> Module.V1.Country |> to_string |> String.replace(~r/\.Country/, "") |> String.to_atom
    Module.V1