当我在Elixir的嵌套模块中使用模块名时,谁能解释这个奇怪的结果?
我发现此代码产生了意外的结果:当我在Elixir的嵌套模块中使用模块名时,谁能解释这个奇怪的结果?,elixir,Elixir,我发现此代码产生了意外的结果: defmodule Foo do defmodule Foo.Bar do def test1 do IO.inspect Foo.Baz end def test2 do IO.inspect Other.Baz end end end > Foo.Foo.Bar.test1 Foo.Foo.Baz > Foo.Foo.Bar.test2 Other.Baz 我希望测试至少能产生一致的
defmodule Foo do
defmodule Foo.Bar do
def test1 do
IO.inspect Foo.Baz
end
def test2 do
IO.inspect Other.Baz
end
end
end
> Foo.Foo.Bar.test1
Foo.Foo.Baz
> Foo.Foo.Bar.test2
Other.Baz
我希望测试至少能产生一致的结果,比如:
# Both have a namespace of Foo
> Foo.Foo.Bar.test1
Foo.Foo.Baz
> Foo.Foo.Bar.test2
Foo.Other.Baz
# or
# Neither has a namespace of Foo
> Foo.Foo.Bar.test1
Foo.Baz
> Foo.Foo.Bar.test2
Other.Baz
但是意外的结果显示它依赖于模块名称的前缀(Foo.Bar
&Foo.Baz
,在test1中),这让我感到惊讶
更新:
由于@mudasobwa的回答,我意识到还有另一个问题
对于这种情况,我们知道B
应该是A.B
,因为我们想直接使用B
:
defmodule A do
defmodule B do
def test do
IO.inspect B
end
end
end
> A.B.test
A.B
但是,为什么B
仍然A.B
defmodule A do
defmodule B.C do
def test do
IO.inspect B
end
end
end
> A.B.C.test
A.B
Foo.Baz
和Other.Baz
都是原子。仅仅是简单的原子,能够用漂亮的圆点和大写字母来书写它们,这就是语法上的糖分。尝试打开IEx
,不加载任何内容,只需键入:
iex(1)> i Foo.Baz
结果是:IEx
知道它,它是一个原子:
iex(1)> i Foo.Baz
Term
Foo.Baz
Data type
Atom
Reference modules
Atom
也就是说,你输出了原子,它们被成功地输出了。它们看起来与模块名称相似的事实是一种情况
但由于这是作为一个模块名表示,Elixir尽量“解决”这些问题。作为“内部模块”,可以从其他模块函数内部调用模块函数,而无需在其前面加上模块名称:
defmodule A do
def a, do: IO.puts "Hello"
def b, do: a # ⇐ this
end
当从a.b
调用时,a
隐式解析为a.a
。嵌入式/嵌套模块也会发生同样的情况:
defmodule A do
defmodule B do
def a, do: IO.puts "Hello"
def b, do: B.a # ⇐ this
end
end
为了使这个B.a
调用成为可能,B.a
实际上被解析为a.B.a
,这是可能的,因为B
本身内部被解析为a.B
您看到的是原子到模块名称外推的一个缺点。我认为这与OP的问题无关。@Dogbert确实,谢谢,出于某种原因,昨天我公布了一半的答案;我原以为它说得很清楚,但现在我重读了一遍,并更新了解释。谢谢你的回答!但我想到了与此相关的另一个问题。我已经更新了这个问题。
B
显然被解析为A.B
,因为它被解析为完整的限定模块名,而不是“this”,或者您所期望的B
在该上下文中是A.B
。恐怕我不明白你期望在那里看到什么。我理解你的例子。但以我的例子A.B.C.test
,我认为B.C
是一个整体,所以我B
不应该是A.B
。然而,从结果来看,我的想法是完全错误的。