如何理解编译的Elixir Erlang函数名

Fil*_*und 8 elixir

在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-

Dog*_*ert 1

我如何解析这个字符串?

'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,但我不确定这意味着什么。