这是一个简单的模块,在函数中有两个断点,它们调用另一个函数,其名称与内置函数完全相同:get/1
和put/2
defmodule Test do
def call_put() do
require IEx; IEx.pry
put("k", "v")
end
def call_get() do
require IEx; IEx.pry
get("k")
end
def put(_k, _v)do
IO.puts("Doing put")
end
def get(_k) do
IO.puts("Doing get")
end
end
在shell中执行:
iex(1)> Test.call_get
Break reached: Test.call_get/0 (lib/test.ex:7)
5: end
6: def call_get() do
7: require IEx; IEx.pry
8: get("k")
9: end
pry(1)> get("a")
:undefined
pry(2)> Test.get("a")
Doing get
:ok
因为它是可见的,所以从调试器调用get/1
会导致执行内置get/1
和put/2
而不是我的Test
模块中的函数。
要正确地工作,我需要命名我的函数调用。谁能解释一下这种行为?
答案 0 :(得分:2)
这里发生的是:背景不同。看:
iex|1 ▶ defmodule Test do
...|1 ▶ def get(p), do: p
...|1 ▶ IO.inspect quote do: (def get(), do: get(42))
...|1 ▶ end
{:def, [context: Test, import: Kernel],
[{:get, [context: Test], []}, [do: {:get, [], '*'}]]}
get/0
函数的AST将包含上下文:
{:get, [context: Test], []}
这就是编译器知道如何调用非限定函数的方法。基本上,在同一模块中调用函数的能力不合格是一种语法糖。在断点处,模块已经编译,并且肯定无法访问“本地”函数,因为不再有“本地”函数。您可以import Test
以不合格的名称获取对函数的访问权限。