[erlang-questions] Calling external modules from a fun

Raimo Niskanen raimo+erlang-questions@REDACTED
Wed Apr 28 17:19:18 CEST 2010


On Wed, Apr 28, 2010 at 12:56:38PM +0200, Alessandro Sivieri wrote:
> 2010/4/28 Raimo Niskanen
> <raimo+erlang-questions@REDACTED<raimo%2Berlang-questions@REDACTED>
> >
> 
> >  I'd say it is entirely true, no false case. The module that
> > created the fun must also exist on the remote node.
> >
> > The fun's code is not transfered to the other node
> > when the fun is sent to the other node. The module
> > that implements the fun has to exist on the other
> > node, and in the same version as on the originating
> > node. Quite some MD5 and other numbering magic
> > is done to ensure that.
> >
> 
> Ah, thank you for your precise answer, even if it screws up some of my
> intentions...
> So if I want to send a function which does not exist in the receiving node,
> I need to send the source code, because the fun itself is not enough; so, in
> a way, I cannot create a closure in the sender, send it to a different node,
> and make the latter execute the function (a remote evaluation in the end),
> right?

Right!

Unless you have a server on the other node that is prepared
to scan and parse arbitrary source code... Or use erl_scan
and erl_parse to make an rpc call to erl_eval, which is
the same thing utilizing only core modules and servers:

Try this on any two nodes (substitute Node2):

    (Node1)1> rpc:call(Node2, erl_eval, exprs,
                       [[{call,1,{remote,1,{atom,1,io},{atom,1,format}},
                          {string,1,"~p~n"},
                          {cons,1,
                           {call,1,{remote,1,{atom,1,erlang},{atom,1,nodes}},
                            []},
                           {nil,1}}]}],
                       []]).
    [Node1]
    {value,ok,[]}
    (Node1)2> 

Where I got the long awful list (Parsed) from:

    {ok,Scanned,_} = erl_scan:string("io:format(\"~p~n\", [erlang:nodes()]).").
    {ok,Parsed} = erl_parse:parse_exprs(Scanned).
    Bindings = erl_eval:new_bindings().

and then

    rpc:call(Node2, erl_eval, exprs, Parsed, Bindings).

There is more in the man pages for erl_eval, erl_parse and erl_scan...

NOTE:
rpc makes the printout [Node1] appear on this node (Node1) since
it sets the process group leader for the rpc process on Node2
that executes erlang:nodes() to be the process group leader
of the shell process on Node1. I.e erlang:nodes() is executed
on Node2 so it says [Node1] and that is printed on the console
of Node1 :-)

> 
> -- 
> Sivieri Alessandro
> alessandro.sivieri@REDACTED
> http://www.chimera-bellerofonte.eu/
> http://www.poul.org/

-- 

/ Raimo Niskanen, Erlang/OTP, Ericsson AB


More information about the erlang-questions mailing list