Elixir 来自_中嵌套的use语句的别名,使用__
假设我有一个模块Elixir 来自_中嵌套的use语句的别名,使用__,elixir,Elixir,假设我有一个模块App.a,它有以下代码 defmodule App.A do defmacro __using__(_) do quote do alias App.B end end end 因此,当使用时,它会自动为App.B添加别名 现在,还有另一个模块名为App.C,定义如下: defmodule App.C do defmacro __using__(_) do quote do use App.A def
App.a
,它有以下代码
defmodule App.A do
defmacro __using__(_) do
quote do
alias App.B
end
end
end
因此,当使用时,它会自动为App.B
添加别名
现在,还有另一个模块名为App.C
,定义如下:
defmodule App.C do
defmacro __using__(_) do
quote do
use App.A
def foo do
B.bar()
end
end
end
end
它添加了一个函数foo
,该函数尝试从模块B
调用函数,而不显式调用
别名,因为我希望使用App.A
已经定义了别名
现在,问题是当我有一些其他模块时,比如App.D
,它使用App.C
,
编译将给我一个警告,说明B未定义,因此alias无法工作
有人能解释一下为什么会发生这种情况吗?别名在使用它们的范围内是局部的。在调用模块的函数中执行使用宏的\uuu的quote
块,因此别名有效。但是,当调用使用App.C
时,别名不在该范围内,因此调用B.bar()将失败
您可以将App.C
更改为:
defmodule App.C do
defmacro __using__(_) do
quote do
use App.A
IO.inspect B == App.B # false
alias App.B
IO.inspect B == App.B # true
def foo do
B.bar()
end
end
end
end
您会注意到,只要别名存在于c.ex中,它就可以工作。在使用之前,您可以在文件中的任何位置定义它:
alias App.B
defmodule App.C do
# alias App.B
defmacro __using__(_) do
# alias App.B
quote do
use App.A
# alias App.B
def foo do
# alias App.B
B.bar()
end
end
end
end