Erlang - spawning processes and passing arguments

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


Short answer: you can't. Spawn (in all it's varying forms) only takes a 0-arity function. Using a closure and bringing in bound variables from the spawning function is the way to go, short of using some sort of shared data store like ETS (which is Monster Overkill).

I've never found using a closure to severely hamper my code structure, though; can you give an example of the problems you're having, and perhaps someone can tidy it up for you?


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

Tags:

Erlang