将模块名称转换为字符串并返回模块

问题描述 投票:0回答:2

如果我们有这样的模块名称:

 Module.V1.CountryTest

我可以将它转换为字符串,如下所示:

   Module.V1.CountryTest |> to_string

现在我得到了一些有趣的结果

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

所以如果我删除

Test
。并将其转换回
atom
。它会给我返回模块名称。但是如果我
replace
remove
模块名称中的任何其他内容,它会给我这个输出:

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

有人可以解释一下这种行为吗?以及为什么它不允许更改或更换任何其他部件。意思是像这样给我返回输出

 Module.V1.Country

我的意思是如果可能的话。

谢谢。

elixir
2个回答
18
投票

Elixir 模块名称只是带有

"Elixir."
前缀的原子。 Elixir 打印以
"Elixir."
开头的原子,并在其后包含有效的 Elixir 模块名称,与其他原子不同:

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

当您替换

Test
时,其余值是有效的 Elixir 模块名称,但是当您也替换
Country
时,最后会得到一个
.
,这不是有效的模块名称。如果你也删除点,你就会得到你想要的:

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

6
投票

要将字符串转换为模块,您可能需要使用

Module.safe_concat/1
/2
:

Module.safe_concat(Module.V1, "CountryTest") # => Module.V1.CountryTest
Module.safe_concat(~w[Module V1 CountryTest]) # => Module.V1.CountryTest
Module.safe_concat(["Module.V1.CountryTest"]) # => Module.V1.CountryTest
© www.soinside.com 2019 - 2024. All rights reserved.