13

我一直遇到这个。我想在不使用 MFA 表单(模块/函数/参数)的情况下生成进程并将参数传递给它们,所以基本上不必导出我想用参数生成的函数。我已经使用闭包(fun's)解决了这个问题,并且让参数只是乐趣之外的绑定值(然后我在乐趣中引用),但是它限制了我的代码结构......我看过docs 和 spawn 只有常规 spawn/1 和 spawn/3 形式,没有别的......

我知道如果不使用 MFA 表单就不可能在生成的进程中重新加载代码,但是生成的进程不是长期运行的,并且完成得相对较快,所以这不是问题(我也想在一个模块中包含所有代码级函数,子作业被放置在该函数内的 funs 中)。

非常感谢谢谢

4

4 回答 4

13

实际上,Richard 为我指出了正确的方向,可以很好地避免这个问题(在回复我在 Erlang GoogleGroups 上发布的同一篇文章时): http ://groups.google.com/group/erlang-programming/browse_thread/线程/1d77a697ec67935a

他的回答:

通过“使用闭包”,我希望你的意思是这样的:

Pid = spawn(fun () -> any_function(Any, Number, Of, Arguments) end)

这将如何限制您的代码结构?

 /Richard 

感谢您及时评论您我的问题。非常感激

于 2009-02-20T22:55:26.193 回答
2

简短的回答:你不能。Spawn(以各种不同的形式)只需要一个 0-arity 函数。使用闭包并从生成函数中引入绑定变量是可行的方法,而不是使用诸如 ETS(即 Monster Overkill)之类的某种共享数据存储。

不过,我从未发现使用闭包会严重妨碍我的代码结构;你能举一个你遇到的问题的例子,也许有人可以帮你整理一下吗?

于 2009-02-20T22:19:21.820 回答
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可以执行具有给定参数的函数的函数。

通过传递函数参考。to 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()带有 args 的 a。

%% 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]).
于 2020-06-29T16:53:21.787 回答
0

首先,没有代码,我们无法为您提供很多帮助,因此使用生成的进程控制函数及其参数的最佳方法是使用接收函数生成进程,然后您将与您的进程联系发送和接收方法,尝试:

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. 

于 2020-06-29T17:52:17.370 回答