Erlang -生成进程和传递参数

8fsztsew  于 2022-12-08  发布在  Erlang
关注(0)|答案(4)|浏览(235)

我一直遇到这种情况。我想生成进程并向它们传递参数,而不使用MFA表单(module/function/arguments),所以基本上不需要导出我想要用参数生成的函数。(fun 's),并让参数成为fun之外的系结值(我随后在有趣的内容中引用了它),但它限制了我的代码结构......我看过文档,spawn只有常规spawn/1和spawn/3形式,没有其他形式......
我知道,如果不使用MFA表单,在派生进程中重新加载代码是不可能的,但是派生进程不是长时间运行的,并且相对较快地完成,所以这不是问题(我还希望将所有代码包含在一个模块级函数中,子作业放在该函数内的函数中)。
非常感谢

piv4azn7

piv4azn71#

actually Richard pointed me in the right direction to take to avoid the issue nicelly (in a reply to the same post I put up on the Erlang GoogleGroups): http://groups.google.com/group/erlang-programming/browse_thread/thread/1d77a697ec67935a

His answer:

By "using closures", I hope you mean something like this:
Pid = spawn(fun () -> any_function(Any, Number, Of, Arguments) end)
How would that be limiting to your code structure?

/Richard

thank you for promptly commenting you my question. Much appreciated

yhived7q

yhived7q2#

简短回答:你不能。Spawn(在它的所有变化形式中)只接受一个零元函数。使用闭包并从Spawn函数中引入绑定变量是可行的方法,除了使用某种共享数据存储,如ETS(这是Monster Overkill)。
但是,我从来没有发现使用闭包会严重妨碍我的代码结构;你能给予一个你遇到的问题的例子吗,也许有人能帮你整理一下?

wvyml7n5

wvyml7n53#

This is an old question but I believe it can be properly answered with a bit of creativity:
The goal of the question is to

  • Invoke a function

With the following limits;

  • No M:F/A formatting
  • No exporting of the Invoked function

This can be solved in the following;
Using the 1st limitation leads us to the following solution:

run() ->
    Module = module,
    Function = function,
    Args = [arg1, arg2, arg3],
    erlang:spawn(Module, Function, Args).

In this solution however, the function is required to be exported.
Using the 2nd limitation (No exporting of the Invoked function) alongside the 1st leads us to the following solution using conventional erlang logic:

run() ->
    %% Generate an anonymous fun and execute it
    erlang:spawn(fun() -> function(arg1, arg2, arg3) end).

This solution generates Anonymous Funs every execution which may or may not be wanted based on your design due to the extra work that the Garbage Colelctor will need to perform (note that, generally, this will be neglible and issues will potentially only be seen in larger systems).
An alternative way to write the above without generating Anonymous Funs would be to spawn an erlang:apply/2 which can execute functions with given parameters.
By passing a Function Ref. to erlang:apply/2 , we can reference a local function and invoke it with the given arguments.
The following implements this solution:

run() ->
    %% Function Ref. to a local (non-exported) function
    Function = fun function/arity,
    Args = [arg1, arg2, arg3],
    erlang:spawn(erlang, apply, [Function, Args]).

Edit: This type of solution can be found within the Erlang Src whereby erlang:apply/2 is being called to execute a fun() with args.

%% 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]).
mtb9vblg

mtb9vblg4#

首先,没有代码,我们不能帮你很多,所以控制你的函数和它们的参数与你的派生进程的最好方法是派生进程与一个接收函数,然后你将联系你的进程在发送和接收方法,尝试:

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.

相关问题