关于 Erlang 函数,尤其是函数的标识符



我有一个关于Erlang函数的问题。查看Erlang shell中的代码:

1> F1 = fun() -> timer:sleep(1000) end.
#Fun<erl_eval.20.111823515>
2> F2 = fun() -> io:format("hello world~n", []) end.
#Fun<erl_eval.20.111823515>

F1F2是不同的,但是为什么它们都有一个标识符#Fun<erl_eval.20.111823515> ?这些神奇的数字意味着什么?


ERTS手册中有一段说:

When interpreting the data for a process, it is helpful to know that anonymous
function objects (funs) are given a name constructed from the name of the
function in which they are created, and a number (starting with 0) indicating
the number of that fun within that function.
我也不明白这段话的意思,你能解释一下吗?

不要从匿名函数的名字中读出太多的含义。您可以安全地从中得到的只是创建它们的模块的名称。你可以试着计算模块中的fun来找到哪个,但我不会麻烦的。

话虽这么说,但这两个基金有相同的名字是有原因的。在shell中输入的表达式不会被编译,而是由模块erl_eval中的解释器计算。这个模块有一个有趣的解释每个元素的乐趣。所以在erl_eval中有一个有趣的地方,#Fun<erl_eval.20.111823515>。不太好,但是很好用。

在一个模块中考虑相同的函数(我们现在不考虑shell)

-module(fun_test).
-export([test/0]).
test() ->
    F1 = fun() -> timer:sleep(1000) end,
    F2 = fun() -> io:format("hello world~n", []) end,
    {F1,F2}.

输出如下

1> fun_test:test().
{#Fun<fun_test.0.78536365>,#Fun<fun_test.1.78536365>}

在上面的示例中,匿名函数对象F1和F2的名称是使用模块名称fun_test,唯一标识符0和1(模块中每个函数的增量),返回地址等在ERTS手册中定义的构造的。这解释了手册中提到的段落。虽然不是很有用,但函数编号在调试期间很方便,因为跟踪中的-test/0-fun-1-将告诉您test/0函数中的匿名函数1是错误的来源。

对于在shell中定义的函数,使用erl_eval模块,如rvirding所述。函数对象声明的结果是erl_eval的返回值。因此,对于那个数,总是返回相同的值。

最新更新