长生不老药支持内省来显示功能起源吗



如果一个模块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.

然后看看哪一个编译不正确。

这只是实现这一目的的另一种方式。

最新更新