如果一个模块import
有多个其他模块,那么给定函数的来源可能并不明显。例如:
defmodule Aimable do
import Camera
import Gun
def trigger do
shoot # which import brought it in?
end
end
我知道有一些方法可以最大限度地减少这种混乱:良好的命名、集中的模块、有针对性的导入(如import Gun, only: [:shoot]
)等。
但是,如果我遇到这样的代码,有没有一种方法可以检查Aimable
并查看函数shoot
的起源?
您可以直接执行此操作:
# from inside the module; IO.inspect(&Aimable.shoot/0) reveals nothing
IO.inspect &shoot/0 #=> &Gun.shoot/0
看看这个
还要记住,不能在两个不同的模块中具有相同arity的相同函数名,并将它们都导入另一个模块中。这将导致调用该函数时出现歧义错误
另一种痛苦的方式。您可以使用function_exported吗/3.规格:
function_exported?(atom | tuple, atom, arity) :: boolean
如果模块已加载并且包含具有给定arity的公共函数,则返回true,否则返回false。
示例:
function_exported?(Gun, :shoot, 0) #=> true
function_exported?(Camera, :shoot, 0) #=> false
使用__ENV__
正如我在另一个问题上了解到的,__ENV__
宏提供了对各种环境信息的访问,包括__ENV__.functions
和__ENV__.macros
。
__ENV__.functions
返回模块元组列表及其提供的函数列表,如:
[{Some.module, [do_stuff: 2]}, {Other.Module, [a_function: 2, a_function: 3]}]
您可以直观地扫描shoot
,或者编写代码进行搜索。
我使用的是Elixir 1.1.0,您所描述的内容似乎是不允许的。这是脚本(在aimable.ex中):
defmodule Gun do
def shoot do
IO.puts "Gun Shot"
end
end
defmodule Camera do
def shoot do
IO.puts "Camera Shot"
end
end
defmodule Aimable do
import Camera
import Gun
def trigger do
shoot
end
end
现在,当我运行iex aimable.ex
时,我会得到一个CompileError
Erlang/OTP 18[erts-7.1][source][64位][smp:4:4][异步线程:10][hipe][kernel poll:false][dtrace]
**(CompileError)可瞄准。例如:18:从相机和枪导入函数射击/0,调用不明确(elixir)src/elixir_dispatch.erl:111::elixir_distatch.expand_import/6(elixir)src/elixir_dispatch.erl:82::elixir_distatch.dispatch_import/5
另一种潜在的技术(为了完整性而添加):
defmodule Aimable do
import Camera, :only [shoot: 0]
import Gun
#etc.
或
defmodule Aimable do
import Camera
import Gun, :only [shoot: 0]
# etc.
然后看看哪一个编译不正确。
这只是实现这一目的的另一种方式。