需要我导出Erlang shell中的所有函数吗?

时间:2012-02-07 08:41:52

标签: erlang

我有这些代码

start() ->
    spawn(?MODULE, init, [self()]).

init(From) ->
    spawn(?MODULE, broadcast, []).    

broadcast() ->
    Msg = "helloworld",
    timer:sleep(10000),
    broadcast().

当我在Erlang shell中测试这些代码时,它给我undef错误,我需要导出播放功能,我只是拒绝

3 个答案:

答案 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).即使代码或函数位于与此相同的模块中: {{1} } 。根据我的个人经验,代码变得易于管理和理解。我得到了一个很好的幻觉,即生成的进程必须从指定的模块中找到函数,然后使用给定的参数执行。

答案 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).