在elixir中定义匿名函数后显示的数字是多少?

And*_*ick 16 elixir

在elixir中定义匿名函数时,会得到这样的结果.

#Function<6.90072148/1 in :erl_eval.expr/5>

我注意到的是这个数字是基于函数的arity.所以总是有1个arg函数

#Function<6.90072148/1 in :erl_eval.expr/5>

总是有两个arg函数

#Function<12.90072148/2 in :erl_eval.expr/5>

总是有三个arg功能

#Function<18.90072148/3 in :erl_eval.expr/5>

返回的数字是多少,它是如何派生的?

Pat*_*ity 14

该数字由索引和函数的唯一名称组成,这些名称由编译器生成.看一下功能检查协议的实现.它包含这段经文:

"#Function<#{uniq(fun_info)}/#{fun_info[:arity]} in " <>
  "#{Inspect.Atom.inspect(mod)}#{extract_name(fun_info[:name])}>"
Run Code Online (Sandbox Code Playgroud)

where fun_info指的是之前调用的结果:erlang.fun_info.这松散地转换为以下伪代码,其中所有内插值都引用以下元素fun_info:

"#Function<#{new_index}.#{uniq}/#{arity} in #{module}.#{name}>"
Run Code Online (Sandbox Code Playgroud)

正如你已经正确观察到的那样,后面的部分/表示了arity.modulename显示功能定义的位置.new_index是指向模块函数表的指针,uniq是编译器生成的模块的哈希值.当您调用:erlang.fun_info函数时,您将能够识别inspect字符串中的值:

iex> fun = fn x -> x end
#Function<6.90072148/1 in :erl_eval.expr/5>

iex> fun_info = :erlang.fun_info(fun)
[pid: #PID<0.58.0>,
 module: :erl_eval,
 new_index: 6,
 new_uniq: <<171, 204, ...>>,
 index: 6,
 uniq: 90072148,
 name: :"-expr/5-fun-4-",
 arity: 1,
 env: [...]]
Run Code Online (Sandbox Code Playgroud)

uniq值和索引一起提供了一种唯一标识匿名函数的方法.请注意,iex对于您创建的所有函数,这些所谓的唯一值内部将非常相似,但是当代码"正确"编译时,它们将是唯一的.考虑以下iex会话:

iex> fn -> end
#Function<20.90072148/0 in :erl_eval.expr/5>
iex> fn -> end
#Function<20.90072148/0 in :erl_eval.expr/5>
iex> fn -> end
#Function<20.90072148/0 in :erl_eval.expr/5>
Run Code Online (Sandbox Code Playgroud)

现在将其与运行以下文件进行比较elixir fun.exs:

IO.inspect fn -> end
IO.inspect fn -> end
IO.inspect fn -> end

# this prints

#Function<0.120576197 in file:fun.exs>
#Function<1.120576197 in file:fun.exs>
#Function<2.120576197 in file:fun.exs>
Run Code Online (Sandbox Code Playgroud)

  • 是的,一开始我也很困惑.发生这种情况是因为`uniq`是模块定义的一种散列函数,在iex中你可以看到`:erl_eval`.`index`也将始终是相同的数字,因为每次eval'd,上下文是相同的,并且计数器从同一点再次开始. (2认同)