如果elixir调试器具有相同的名称,为什么调用内置函数而不是我的函数

时间:2017-09-08 12:27:19

标签: debugging erlang elixir beam

这是一个简单的模块,在函数中有两个断点,它们调用另一个函数,其名称与内置函数完全相同:get/1put/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/1put/2而不是我的Test模块中的函数。 要正确地工作,我需要命名我的函数调用。谁能解释一下这种行为?

1 个答案:

答案 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以不合格的名称获取对函数的访问权限。