我一直在努力。我想生成进程并传递参数 他们没有使用MFA表格(模块/函数/参数),所以 基本上无需导出我想要生成的函数 参数。我使用闭包(乐趣)几次绕过这个 并且让参数只是在乐趣之外被绑定的值(然后我在乐趣中引用),但是它 限制我的代码结构......我只看了文档和产生 有常规的spawn / 1和spawn / 3形式,没有别的......
我理解,如果不使用MFA表单,生成的进程中的代码重新加载是不可能的,但是生成的进程不具有长期运行性并且相对快速地完成,因此这不是问题(我还想包含所有代码在一个模块级函数中,子作业被放置在该函数内部。)
非常感谢 谢谢答案 0 :(得分:12)
实际上,理查德指出我正确的方向,以避免这个问题(在我对Erlang GoogleGroups的同一篇文章的回复中): http://groups.google.com/group/erlang-programming/browse_thread/thread/1d77a697ec67935a
通过“使用闭包”,我希望你的意思是这样的:
Pid = spawn(fun() - > any_function(Any,Number,Of,Arguments)结束)
这会如何限制您的代码结构?
/Richard
感谢您及时评论我的问题。非常感谢
答案 1 :(得分:1)
简短的回答:你做不到。 Spawn(以其各种形式)仅采用0-arity函数。使用闭包并从产生函数引入绑定变量是可行的方法,而不是像ETS那样使用某种共享数据存储(Monster Overkill)。
我从未发现使用闭包来严重阻碍我的代码结构;你能举例说明你遇到的问题,或许有人可以为你整理一下吗?
答案 2 :(得分:1)
这是一个古老的问题,但我相信可以通过一点点创造力来正确回答:
问题的目标是
具有以下限制;
M:F/A
格式这可以在下面解决;
使用第一个限制会导致我们找到以下解决方案:
run() ->
Module = module,
Function = function,
Args = [arg1, arg2, arg3],
erlang:spawn(Module, Function, Args).
但是,在此解决方案中,该功能需要导出。
与第二个限制一起使用第二个限制(不导出调用的函数)会导致我们使用常规的erlang逻辑得出以下解决方案:
run() ->
%% Generate an anonymous fun and execute it
erlang:spawn(fun() -> function(arg1, arg2, arg3) end).
由于垃圾收集器需要执行额外的工作,因此该解决方案会根据您的设计在每次执行时都可能会生成“匿名乐趣”(请注意,通常,这将是可忽略的,而问题只会是在较大的系统中可以看到)。
编写上面的而不产生的匿名乐趣的另一种方法是生成erlang:apply/2
,它可以执行具有给定参数的功能。
通过传递功能参考。到erlang:apply/2
,我们可以引用本地函数并使用给定的参数调用它。
以下实现了此解决方案:
run() ->
%% Function Ref. to a local (non-exported) function
Function = fun function/arity,
Args = [arg1, arg2, arg3],
erlang:spawn(erlang, apply, [Function, Args]).
编辑:可以在Erlang Src中找到这种类型的解决方案,据此,调用erlang:apply/2
以执行带有实参的fun()
。
%% https://github.com/erlang/otp/blob/71af97853c40d8ac5f499b5f2435082665520642/erts/preloaded/src/erlang.erl#L2888%% Spawn and atomically set up a monitor.
-spec spawn_monitor(Fun) -> {pid(), reference()} when
Fun :: function().
spawn_monitor(F) when erlang:is_function(F, 0) ->
erlang:spawn_opt(erlang,apply,[F,[]],[monitor]);
spawn_monitor(F) ->
erlang:error(badarg, [F]).
答案 3 :(得分:0)
首先,没有代码,我们不能为您提供很多帮助,因此,使用生成的过程来控制函数及其args的最佳方法是使用接收函数生成该过程,然后您将与您在发送和接收方法中的过程,请尝试:
Pid=spawn(Node, ModuleName, functionThatReceive, [])
%%or just spawn(ModuleName....) if the program is not %%distributed
Pid ! {self(), {M1, f1, A1}},
receive
{Pid, Reply} ->Reply
end,
Pid ! {self(), {M2, f2, A2}},
receive
{Pid, Reply} ->Reply
end,
.......
functionThatReceive() ->
receive
{From, {M1, f1, A1}} ->From ! {self(), doSomething1} ;
{From, {M2, f2, A2}} ->From ! {self(), doSomething2}
end.