Почему отладчик elixir вызывает встроенную функцию вместо моей, если они имеют одинаковые имена
Вот простой модуль с двумя точками останова в функциях, которые вызывают другие функции с именами, точно такими же, как встроенные: 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
Выполнение этого в оболочке:
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
модуль. Для правильной работы мне нужно пространство имен для вызова моей функции. Может ли кто-нибудь объяснить мне это поведение?
1 ответ
То, что здесь происходит: контекст отличается. Посмотрите:
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
функция будет включать контекст:
{:get, [context: Test], []}
Так компилятор знает, что вызывать для неквалифицированных функций. По сути, возможность вызывать функцию из одного и того же модуля без оговорок является синтаксическим сахаром. Находясь в точке останова, модуль уже скомпилирован, и, безусловно, нет доступа к "локальным" функциям, поскольку больше нет "локальных" функций. Ты можешь import Test
получить доступ к функциям по их неквалифицированным именам.