在ExProf中,Elixir函数名称在编译后打印出我假设的Erlang名称.一个例子是
Enum.reduce/3
Run Code Online (Sandbox Code Playgroud)
印刷为
'Elixir.Enum':'-reduce/3-lists^foldl/2-0-'/3
Run Code Online (Sandbox Code Playgroud)
我该如何解析这个字符串?这个-lists^foldl/2-0-部分来自哪里?为什么有多个/3?为什么有些名字有-前缀?什么^意思?为什么2-0-?
我如何解析这个字符串?
'Elixir.Enum':'-reduce/3-lists^foldl/2-0-'/3是 Erlang 中的函数引用语法,引用-reduce/3-lists^foldl/2-0-module 中命名的函数,数量为 3,与Elixir 中Elixir.Enum类似。&Enum."-reduce/3-lists^foldl/2-0-"/3
该
-lists^foldl/2-0-零件从哪里来?
这-$fn/$arity-$something-$count-是 Erlang 在堆栈跟踪(显然是分析输出)中为 内部定义的匿名函数返回的名称$fn/$arity。通常,您会看到类似的内容-main/0-fun-0-,$something == "fun"例如:
defmodule Foo do
def main do
try do
(fn -> raise("foo") end).()
rescue
_ -> IO.inspect System.stacktrace
end
end
end
Run Code Online (Sandbox Code Playgroud)
印刷:
[{Foo, :"-main/0-fun-0-", 0, [file: 'foo.ex', line: 4]},
{Foo, :main, 0, [file: 'foo.ex', line: 4]},
{:erl_eval, :do_apply, 6, [file: 'erl_eval.erl', line: 670]},
{:elixir, :erl_eval, 3, [file: 'src/elixir.erl', line: 223]},
{:elixir, :eval_forms, 4, [file: 'src/elixir.erl', line: 211]},
{Code, :eval_string, 3, [file: 'lib/code.ex', line: 168]},
{Kernel.CLI, :wrapper, 1, [file: 'lib/kernel/cli.ex', line: 437]},
{Enum, :"-map/2-lists^map/1-0-", 2, [file: 'lib/enum.ex', line: 1184]}]
Run Code Online (Sandbox Code Playgroud)
只是您不太可能-fun-在 Elixir 的默认错误消息中看到错误消息,因为在本例中它们已标准化anonymous fn/0 in Foo.main/0(这就是我通过显式调用打印上面的堆栈跟踪的原因System.stacktrace/0)。
那么它从哪里来呢lists^foldl/2?它是由定义编译属性的模块调用的模块( Elixir 中的模块确实这样做)生成的sys_core_fold_lists,该模块“从列表模块中内联高阶列表函数”。此内联还将名称“lists^foldl/2”赋予匿名函数,而不仅仅是“有趣”。sys_core_foldinline_list_funcsEnum
这是一个简单的演示:
defmodule Fold do
@compile :inline_list_funcs
def main do
sum([1, 2, 3])
end
def sum(list) do
:lists.foldl(fn a, b -> raise "foo" end, 0, list)
end
end
Fold.main
Run Code Online (Sandbox Code Playgroud)
对于@compile :inline_list_funcs,输出为:
** (RuntimeError) foo
fold.exs:9: anonymous fn/2 in Fold.sum/1
fold.exs:9: Fold."-sum/1-lists^foldl/2-0-"/3
(elixir) lib/code.ex:363: Code.require_file/2
Run Code Online (Sandbox Code Playgroud)
如果没有它,输出是:
** (RuntimeError) foo
fold.exs:9: anonymous fn/2 in Fold.sum/1
(stdlib) lists.erl:1263: :lists.foldl/3
(elixir) lib/code.ex:363: Code.require_file/2
Run Code Online (Sandbox Code Playgroud)
使用该属性,lists即使我们显式调用:lists:foldl.
为什么有多个
/3?
这似乎是 Erlang 的副作用,包括命名匿名函数时当前函数的数量。
为什么有些名字
-要加前缀?
上面解释过。
是什么
^意思?
这只是一个sys_core_fold_lists:call/4选择的名字。
为什么
2-0-?
2来自sys_core_fold_lists:call/4. 0被称为“计数”Exception.format_mfa/3,但我不确定这意味着什么。