Doubt about funs

Robert Virding rv@REDACTED
Wed Feb 21 19:55:38 CET 2001

Lon Willett <Lon.Willett@REDACTED> writes:
>So has anyone considered implementing a syntax like "fun Mod:Fun/Arity"?
>It seems like an obvious thing to do.  And even a naive implementation
>which just replaced the expression with "{M,F}" (losing the arity)
>would at least provide a nice consistent way to express the intent.  A
>good implementation would produce some dynamic function object that
>was efficient, contained the arity, and was robust across code change.

This was considered but there did not seem to be any point seeing it can
easily be had with "fun (A, ...) -> m:f(A, ...) end".  This, by the way,
will handle module updates of module m as it is just a normal call.

Some other significant benefits with a fun which cannot be handles by 
{M,F} are:

1. The fun "function", the one automatically created, doesn't have to be
exported and allows you to keep tighter control of your interface. 

2. A fun is a closure over the variable bindings when it was created so 
it "imports" free variables.  This is a big one.  For example:

incrementer(X) -> fun (Y) -> Y+X end.

and calling incrementer(15) returns a function which increments a vlue 
by 15.

2. Using spawn/1/2 and funs allow you create processes without 
exporting "internal" functions.  Plus the closure (but be careful to 
keep track of when things are done!).

Ulf Wiger <etxuwig@REDACTED> writes:
>On Wed, 21 Feb 2001, Martin Bjorklund wrote:
>>Ulf Wiger <etxuwig@REDACTED> wrote:
>>> Since funs are actually made into real functions by the compiler, they
>>> seem to have roughly the same properties as ordinary functions during
>>> code change. I've run some tests, and it does seem to be the case that
>>> as long as the fun is tail recursive (doesn't wait for a return
>>> value), then upgrading doesn't break the fun as long as the arity
>>> stays the same. This is the same as for ordinary functions.
>>erik> What you describe will happen in the current implementation if
>>erik> the function defining F is changed (or any funs are added or
>>erik> removed before the fun defining F). 
>Yes, you're right. Adding a fun before a fun referenced by some
>process P, will cause P to crash when the old module is purged.

There is a little misconception about the implementation here.  Yes, a
normal Erlang function is created for a fun with a funny name which
actually gives some indication of where the fun is defined, at least in
which function.  The fun "object" contains a (indirect) reference to
this *name*.  It also contains the module name and a unique module id.

This means that:

1. The module name and id mean that you can call funs which are defined 
in the old version of code, not just in the new version.  A fun is 
therefore usable over one module update.

2. There are no problems when updating a module about moving things, 
add/removing funs etc.  A fun contains an identifier to which version 
of a module it was defined in, it won't just test the new version.

3. Seeing funs reference a module and do not contain the code they run
they don't "live forever" like other data, or rather are "usable
forever".  When the module has been pruged out you can no longer call
the fun.  But they are safe during their lifetime.

Getting back to the {M,F} versus fun question.  They actually *mean* two
different things even though the syntax for using them is the same. 
As long as you are aware of this then there are no real problems.  I 
personally never use {M,F} and only use funs for temporary things, like 
for higher-order functions.  I have had no problems with module 
versions, but then again my funs are short lived.


More information about the erlang-questions mailing list