Why create illusion that you are sending a Fun to remote node to execute in a new process? If client node has to have same module loadable with the Fun defined as a server node anyway. Why not only spawn(Node, M, F, A) then, which makes it clear that you are sending a definition of a function call, not Fun itself.
In this article, we will discuss the difference between spawn () and fork () methods in Node.js. Both are ways to create child processes in Node.js in order to handle increasing workloads. Spawn () method: The spawn process initiates a command in a new process. We can pass the command as an argument to it.
Example: This is a very simple and general example of the use of spawn. We first required spawn by destructuring, then create a child process by passing arguments. Then register a stdout event on that child process. Message sent from child.js is printing in file server.js due to the use of fork child process.
The different shell can be specified as a string. The default value is false which implies no shell. Return Value: It returns an instance of the child process. Example: This is a very simple and general example of the use of spawn. We first required spawn by destructuring, then create a child process by passing arguments.
The default value is an empty array. shell: Accepts a boolean value. If true, runs the command inside of a shell. The different shell can be specified as a string. The default value is false which implies no shell. Return Value: It returns an instance of the child process. Example: This is a very simple and general example of the use of spawn.
Let's consider two possible cases
Fun = fun file:getcwd/0,
erlang:spawn(Node, Fun).
In this case Fun
indeed should be loadable at the remote side.
Fun = fun() -> io:format("My node is ~p~n", [node()]) end,
erlang:spawn(Node, Fun).
They are callable also.
While there some limitations implied to a function, that can be spwaned remotely, this form is still suitable and can be dropped, because then second case would become impossible
Some misconceptions might go from this article
Actually, if you run erlang:fun_info
for anonymous function, you'll see, that it provides implementation in a form of AST
(b@lol4t0-home)21> rp(erlang:fun_info(fun() -> io:format("My node is ~p~n", [node()]) end)).
[{pid,<0.96.0>},
{module,erl_eval},
{new_index,20},
{new_uniq,<<99,62,121,82,122,95,246,237,63,72,118,40,4,
25,16,50>>},
{index,20},
{uniq,52032458},
{name,'-expr/5-fun-3-'},
{arity,0},
{env,[{[],
{eval,#Fun<shell.21.31625193>},
{value,#Fun<shell.5.31625193>},
[{clause,1,[],[],
[{call,1,
{remote,1,{atom,1,io},{atom,1,format}},
[{string,1,"My node is ~p~n"},
{cons,1,{call,1,{atom,1,node},[]},{nil,1}}]}]}]}]},
{type,local}]
The example below shows that the remote node can execute a code that was never loaded on it, even a call to an anonymous function that was defined on the caller node:
on node titi
Erlang/OTP 19 [erts-8.0] [64-bit] [smp:4:4] [async-threads:10]
Eshell V8.0 (abort with ^G)
(titi@XXXXXXXX)1> net_adm:ping(toto@XXXXXXXX).
pong
(titi@XXXXXXXX)2> F = fun F(X) -> receive {plus,N} -> F(X+N); get -> io:format("state is ~p~n",[X]), F(X); stop -> bye end end.
#Fun<erl_eval.30.52032458>
(titi@XXXXXXXX)3> G = fun() -> register(server,self()), F(0) end.
#Fun<erl_eval.20.52032458>
(titi@XXXXXXXX)4> spawn(toto@XXXXXXXX,G).
<7039.67.0>
state is 0
state is 5
state is 10
(titi@XXXXXXXX)5>
on node toto
Erlang/OTP 19 [erts-8.0] [64-bit] [smp:4:4] [async-threads:10]
Eshell V8.0 (abort with ^G)
(toto@XXXXXXXX)1> server ! get. % will print state is 0
get
(toto@XXXXXXXX)2> server ! {plus,5}. % new state = 5
{plus,5}
(toto@XXXXXXXX)3> server ! get. % will print state is 5
get
(toto@XXXXXXXX)4> server ! {plus,5}. % new state = 10
{plus,5}
(toto@XXXXXXXX)5> server ! get. % will print state is 10
get
(toto@XXXXXXXX)6> server ! stop. % ends the server process
stop
(toto@XXXXXXXX)7> server ! get. % message will fail
** exception error: bad argument
in operator !/2
called as server ! get
(toto@XXXXXXXX)8>
I also checked that if you replace the code {plus,N} -> F(X+N);
by {plus,N} -> F(maps:put(X,X+N,maps:new()));
which is calling a module not loaded by the shell at start, it works fine as well.
Edit
Read the comments, it seems that doing the test in the shell is not the right way, 2 conclusions though:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With