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

时间:2016-07-21 15:01:52

标签: elixir

在ExProf中,Elixir函数名称在编译后打印出我假设的Erlang名称。一个例子是

Enum.reduce/3

打印为

'Elixir.Enum':'-reduce/3-lists^foldl/2-0-'/3

如何解析此字符串? -lists^foldl/2-0-部分来自哪里?为什么有多个/3?为什么有些名称-有前缀? ^是什么意思?为什么2-0-

2 个答案:

答案 0 :(得分:1)

  

如何解析此字符串?

'Elixir.Enum':'-reduce/3-lists^foldl/2-0-'/3是Erlang中的函数引用语法,引用模块-reduce/3-lists^foldl/2-0-中名为Elixir.Enum的函数,其中arity为3,类似于Elixir中的&Enum."-reduce/3-lists^foldl/2-0-"/3

  

-lists^foldl/2-0-部分来自哪里?

-$fn/$arity-$something-$count-是Erlang在stacktraces中返回的名称(显然是剖析输出),用于$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

打印:

[{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]}]

只是你不太可能在Elixir的默认错误消息中看到-fun-个,因为它们是normalized,在这种情况下是anonymous fn/0 in Foo.main/0(这就是为什么我打印了通过明确调用System.stacktrace/0来进行堆栈跟踪。

那么lists^foldl/2来自哪里?这是generated by sys_core_fold_lists,模块called by sys_core_fold,用于定义inline_list_funcs编译属性(Elixir does do that中的Enum模块)的模块,其中“内联高阶列表函数来自列出模块“。这个内联还给匿名函数命名“lists ^ foldl / 2”,而不仅仅是“有趣”。

这是一个简单的演示:

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

使用@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

没有它,输出是:

** (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

使用该属性,我们没有lists模块的任何堆栈跟踪条目,即使我们明确调用:lists:foldl

  

为什么有多个/3

这似乎是Erlang的副作用,包括命名匿名函数时当前函数的arity。

  

为什么某些名称-带有前缀?

上面解释。

  

^是什么意思?

这只是sys_core_fold_lists:call/4选择的名称。

  

为什么2-0-

2来自sys_core_fold_lists:call/40referred to as "count" in Exception.format_mfa/3,但我不确定这意味着什么。

答案 1 :(得分:0)

它是Enum.reduce实现中某些“匿名”函数的生成名称。我假设这个函数是内联定义的,并作为参数传递给lists:foldl,因此得名。 AFAIK这样的名字不是由Elixir产生的,而是由Erlang本身产生的。