remote execution of funs in shell =/= in erts

Raimo Niskanen raimo@REDACTED
Fri Nov 26 09:03:57 CET 2004

Congratulations on your educated guesses, they are perfectly correct!

To elaborate some more: erl_eval has got a bunch of compiled funs itself,
of all arities up to 20 that it uses when evaluating funs. When they are
evaluated they are called with the actual arguments of the emulated call
and they get they emulated environment as well as the parse tree code
to evaluate as their actual environment.

So when the shell evaluates a fun of arity N, it always calls the same
fun of arity N that is compiled in the module erl_eval, but with different
environment depending on the emulated fun's code and bound variables, and 
since erl_eval almost certainly exists on the remote node, it can be remote
called - the parse tree gets sent to the remote node. If you have different
versions of erl_eval on the nodes you cannot do remote fun evaluation.

And, if you try to evaluate a fun with more than 20 arguments in the shell
(in erl_eval) it will fail.

matthias@REDACTED (Matthias Lang) writes:

> Peter-Henry Mander writes:
>  > So I guess that there's a difference between how the shell executes
>  > remote funs and how the Erlang runtime executes remote funs. How do
>  > nodes communicate what appears to be version information or beam digest
>  > or checksums beween them? Is this documented (otherwise than by reading
>  > code :-)? 
> There are quite a few questions there. I don't know enough about the
> ERTS internals to answer all of them confidently, but I'll have a go.
> Yes, there's a difference between funs made in the shell and funs made
> in code. An easy way to see that is to run term_to_binary() on the
> 'same' fun made two different ways:
> 8> io:fwrite("~w", [term_to_binary(e:a())]).              
> <<131,112,0,0,0,66,1,119,221,89,18,158,97,22,203,233,28,220,41,82,49,106,16,0,0,0,0,0,0,0,0,100,0,1,101,97,0,98,5,195,163,107,103,100,0,13,110,111,110,111,100,101,64,110,111,104,111,115,116,0,0,0,46,0,0,0,0,0>>ok
> 9> io:fwrite("~w", [term_to_binary(fun(X) -> 2 * X end)]). 
> <<131,112,0,0,0,227,1,242,35,237,99,76,83,218,107,189,28,220,154,229,136,183,25,0,0,0,1,0,0,0,3,100,0,8,101,114,108,95,101,118,97,108,97,5,98,3,208,36,215,103,100,0,13,110,111,110,111,100,101,64,110,111,104,111,115,116,0,0,0,46,0,0,0,0,0,104,3,100,0,4,101,118,97,108,104,2,100,0,5,115,104,101,108,108,100,0,10,108,111,99,97,108,95,102,117,110,99,108,0,0,0,1,103,100,0,13,110,111,110,111,100,101,64,110,111,104,111,115,116,0,0,0,22,0,0,0,0,0,106,106,108,0,0,0,1,104,5,100,0,6,99,108,97,117,115,101,97,1,108,0,0,0,1,104,3,100,0,3,118,97,114,97,1,100,0,1,88,106,106,108,0,0,0,1,104,5,100,0,2,111,112,97,1,100,0,1,42,104,3,100,0,7,105,110,116,101,103,101,114,97,1,97,2,104,3,100,0,3,118,97,114,97,1,100,0,1,88,106,106>>
> (e:a() is the 'same' fun as the one I entered in the shell).
> Taking a quick look at the source (erl_fun.h), it appears that a
> 'normal' fun includes an MD5sum of the module which created it, which
> tallys with your observations. Taking an educated guess, a 'shell fun'
> is actually a parse tree.
> I would be surprised if it's possible to execute a compiled fun
> without making the exact same code available at the other node, but
> you don't necessarily have to do that via a filesystem.
>  > Is it possible for the runtime to execute a remote fun without
>  > the corresponding beam being available on the remote node, like the
>  > shell appears to do?
> I don't think there's a clean way of doing it. One dirty way is to use
> erl_scan, erl_parse and erl_eval. I'd guess that's what the shell
> does.
> Matt


/ Raimo Niskanen, Erlang/OTP, Ericsson AB

More information about the erlang-questions mailing list