Debugging 为什么elixir调试器在调用内置函数而不是我的函数时使用相同的名称
下面是一个简单的模块,函数中有两个断点,这些断点调用另一个与内置函数名称完全相同的函数:Debugging 为什么elixir调试器在调用内置函数而不是我的函数时使用相同的名称,debugging,erlang,elixir,beam,Debugging,Erlang,Elixir,Beam,下面是一个简单的模块,函数中有两个断点,这些断点调用另一个与内置函数名称完全相同的函数: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
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
模块中的函数。
为了正常工作,我需要为我的函数调用命名名称空间。有人能给我解释一下这种行为吗?这里发生的事情是:环境不同。看:
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
通过函数的非限定名称访问函数 这里发生的事情是:上下文不同。看:
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
通过函数的非限定名称访问函数 我认为当前模块的功能不会在IEx.pry
会话中自动“导入”。您可以在会话启动时执行import Test
。我认为当前模块的功能不会在IEx.pry
会话中自动“导入”。你可以在会话启动时进行导入测试。我不认为“从同一个模块中调用函数的能力”是“语法糖”,因为这两件事的行为是不一样的。请参见此处解释的完全限定函数调用与常规调用:。当我从内部运行quote do:(def get(),do:get(42))
时,我也会得到完全相同的AST,就像您所做的那样,如果我从iex会话运行它,OP的代码就会启动,因此我认为这不是本地调用不起作用的原因。如果我在一个全新的iex
会话中运行代码,我确实会得到一个context:Elixir
的AST。我不认为“从同一模块中调用函数的能力”是“语法糖”,因为这两种东西的行为是不一样的。请参见此处解释的完全限定函数调用与常规调用:。当我从内部运行quote do:(def get(),do:get(42))
时,我也会得到完全相同的AST,就像您所做的那样,如果我从iex会话运行它,OP的代码就会启动,因此我认为这不是本地调用不起作用的原因。如果我在全新的iex
会话中运行代码,我确实会得到一个带有context:Elixir
的AST。