Elixir是否支持内省以显示功能来源?

时间:2015-12-17 01:32:42

标签: elixir

如果模块$('.stLarge[style*="background-image: url(http://w.sharethis.com/images/facebook_32.png)"]').css("background-image", "url(/images/facebook.png)"); 是多个其他模块,那么给定函数的来源可能并不明显。例如:

import

我知道有办法减少这种混淆:良好的命名,专注的模块,目标导入,如defmodule Aimable do import Camera import Gun def trigger do shoot # which import brought it in? end end 等。

但如果我遇到这样的代码,有没有办法检查import Gun, only: [:shoot]并查看函数Aimable的来源?

4 个答案:

答案 0 :(得分:6)

您可以直接执行此操作:

# from inside the module; IO.inspect(&Aimable.shoot/0) reveals nothing
IO.inspect &shoot/0 #=> &Gun.shoot/0

Check this out

还要记住,在两个不同的模块中,不能将相同的功能名称与相同的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

答案 1 :(得分:3)

使用__ENV__

在我了解on another question后,__ENV__宏可以访问various environment info,包括__ENV__.functions__ENV__.macros

__ENV__.functions返回模块元组列表及其提供的函数列表,如:

[{Some.module, [do_stuff: 2]}, {Other.Module, [a_function: 2, a_function: 3]}]

您可以直观地扫描shoot,或编写代码来搜索它。

答案 2 :(得分:1)

我正在使用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] [来源] [64位] [smp:4:4]   [async-threads:10] [hipe] [kernel-poll:false] [dtrace]

     

**(CompileError)aimable.ex:18:从相机和枪输入的功能拍摄/ 0,调用不明确       (elixir)src / elixir_dispatch.erl:111 :: elixir_dispatch.expand_import / 6       (elixir)src / elixir_dispatch.erl:82 :: elixir_dispatch.dispatch_import / 5

答案 3 :(得分:0)

另一种潜在技术(为了完整性而添加):

defmodule Aimable do
  import Camera, :only [shoot: 0]
  import Gun

#etc.

defmodule Aimable do
  import Camera
  import Gun, :only [shoot: 0]

# etc.

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

实现这一目标的另一种方法。