我有这些代码
start() ->
spawn(?MODULE, init, [self()]).
init(From) ->
spawn(?MODULE, broadcast, []).
broadcast() ->
Msg = "helloworld",
timer:sleep(10000),
broadcast().
当我在Erlang shell中测试这些代码时,它给我undef错误,我需要导出播放功能,我只是拒绝
答案 0 :(得分:5)
代码
spawn(?MODULE, init, [self()]).
表示您将生成哪个初始调用为?MODULE:init(self())
或更准确等效于apply(?MODULE,init,[self()])
的进程。 ?MODULE
被宏评估为当前模块名称,但无论如何它是外部函数调用,因此即使使用?MODULE
也必须导出此函数。相反
spawn(fun() -> init(self()) end).
通过对func fun() -> init(self()) end
的初始调用生成,该函数使用函数init/1
的结果调用self()
。这是本地调用,这意味着init/1
可能无法导出。在新进程中执行self()
时,还有另一个问题,因此您必须编写
Self = self(), spawn(fun() -> init(Self) end).
与spawn(?MODULE, init, [self()])
中的效果相同,其中self()
被评估为spawn/3
的参数。
答案 1 :(得分:1)
好吧,函数broadcast
在一个进程中执行。因此,所有进程都必须可以访问此功能。即使同一个源代码在同一个模块中生成一个从同一模块执行函数的进程,该函数也必须从该模块中导出才能使其可访问。
这让我了解spawn(fun() -> broadcast() end).
和spawn(?MODULE, broadcast, [])
之间的区别。后者称为Spawning with MFA
。在此方法中,必须将该函数导出模块,以便可以执行该函数。然而前者是唯一的,它是fun
。
要了解此方法:spawn(fun() -> broadcast() end).
,我们需要将其与此方法进行比较:spawn(fun() -> ?MODULE:broadcast() end).
。现在,让我们谈谈后两者
spawn(fun() -> ?MODULE:broadcast() end).
broadcast
未在模块中导出: ?MODULE
,进程将崩溃。请注意,在这种情况下,该函数位于编写此源代码的模块中。 spawn(fun() -> broadcast() end).
?MODULE
中。spawn(fun() -> ?MODULE:broadcast() end).
或spawn(fun() -> some_module:broadcast() end).
即使代码或函数位于与此相同的模块中:
答案 2 :(得分:0)
仔细查看警告:
test.erl:8: Warning: function init/1 is unused
test.erl:8: Warning: variable 'From' is unused
test.erl:11: Warning: function broadcast/0 is unused
test.erl:12: Warning: variable 'Msg' is unused
编译器认为您的其他函数未使用且从不编译它们。试试这个:
start() ->
spawn(fun() -> init(self()) end).
init(From) ->
spawn(fun() -> broadcast() end).