[erlang-questions] Calling external modules from a fun

Raimo Niskanen raimo+erlang-questions@REDACTED
Wed Apr 28 12:21:34 CEST 2010


On Fri, Apr 23, 2010 at 01:00:46PM -0500, Scott Lystig Fritchie wrote:
> David Mercer <dmercer@REDACTED> wrote:
> 
> dm> Since no-one smarter than me responded, here's my take.
> 
> I don't claim to be any smarter on this subject, but there's some
> empirical study possible while we wait for wisdom.
> 
> dm> In order for a fun to work on a remote node, the module that created
> dm> the fun must also exist on the remote node.
> 
> True and false.  If you use this syntax, yes, there's a module
> dependency:
> 
>     spawn(Node, fun some_module:foo_func/0).

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.

> 
> There's a noticable difference in the sizes of:
> 
>     size(term_to_binary(fun some_module:foo_func/0)).
>     size(term_to_binary(fun() -> some_module:foo_func() end)).
> 
> If the fun uses the fun() -> ... end syntax, then any function calls
> made externally must be resolvable by the VM, the code server, etc.  So
> "fun() -> erlang:display(42) end" will work because the BIF definitely
> exists over on the remote node ... because it's a BIF.

No, that would not work since the code that calls erlang:display(42)
must exist on the other node. I.e the fun code body.

Sending fun erlang:display/0 would work since what is sent
in this case is just the entry point, which exists on the other node.

Sending fun some_module:foo_func/0 works up to the point
where it is called. It is just the entry point that is
transferred. In this case some_module:foo_func()
is called regardless of which code implements it. If
there is such a function it is called.

Sending fun () -> some_module:foo_func() end also will
work up to the point where it is called. Same as always
it is only the entry point that is transferred. This
entry point has a larger encoding since it contains
module MD5 sums and other stuff to ensure that exactly
that the code that the originating node expects is
implementing the fun on te other node. When it is called,
the module in which "fun () -> ... end" was compiled must exist
on the other node. If it does it is executed and calls
whatever function that is registered as some_module:foo_func/0
so such a module/function must also exist or that call will fail.

> 
> The same resolvability property can be seen when using intra-module
> calls.  Using size(term_to_binary(Fun)), we see create experiments that
> show that all of the transitively dependent functions are not included
> in the fun because the size won't change.
> 
> -Scott
> 
> ________________________________________________________________
> erlang-questions (at) erlang.org mailing list.
> See http://www.erlang.org/faq.html
> To unsubscribe; mailto:erlang-questions-unsubscribe@REDACTED

-- 

/ Raimo Niskanen, Erlang/OTP, Ericsson AB


More information about the erlang-questions mailing list