0

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

4

1 回答 1

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, [], '*'}]]}

函数的 ASTget/0将包括上下文:

{:get, [context: Test], []}

这就是编译器如何知道为不合格的函数调用什么的方式。基本上,从同一个模块中不合格地调用函数的能力是一种语法糖。在断点中,模块已经编译,并且肯定无法访问“本地”函数,因为不再有“本地”函数。您可能会import Test通过它们的非限定名称来访问这些函数。

于 2017-09-08T13:53:53.667 回答