Doubt about funs
Martin Bjorklund
mbj@REDACTED
Wed Feb 21 09:52:58 CET 2001
"Erik Johansson" <happi@REDACTED> wrote:
> The point is really that you should not hold on to funs over code
> change.
That's what I tried to say. I objected to Richard's statement that
a fun() is always prefered over {M,F} tuples.
> But there is no reason to do so either. If the code defining the fun is
> changed then the code that applies the fun should get a new fun.
How do you propose this should be done in practise? You'd have to
make sure that all processes (ets tables, files, ...) which holds a
function gets notified when the new code is loaded. This is simply
not feasible.
> You could run in to similar problems with F = {m,f} if you change the module
> m so that f does not exist, or the arity of f changes, or the implementation
> of f changes, then applying F is not a good idea.
Of course, but in that case the programmer made the choice to change
or remove the function. With a fun, this happens whether the
programmer wants it or not.
> It might even be an argument for using a fun instead of a tuple in the
> current implementation:
> * If a process is holding on to a fun and the implementation of the fun is
> changed twice then that process is killed, and the supervisor can start up
> the process again in a correct way.
Surely you can't be serious. Code change by crashing might be an
interesting area of research ;-)
> * If a process is holding on to a mod-fun-tuple then the run-time system
> can't detect this and the process will keep on living and applying {m, f}
> even if the intention of the new code would be to apply {m, g}.
Again, this is under the control of the prgrammer with {M,F}.
> > > (For the same reason, it is better to use spawn/1 and spawn/2 than the
> old spawn/3 and
> > > spawn/4, if possible. Avoid `apply/3'.)
> >
> > No! Using spawn/1 or spawn/2 is even worse if you want to support
> > code upgrade. This means that the process will have a reference to
> > the fun on it's stack, which it never will get rid of. Thus, loading
> > two more versions of the module kills the process.
>
> No! That is not true.
> (Unless the fun is not tail-recursive, but that is not specific for funs.
> If you want to support code upgrade you will use tail-recursive functions
> as much as possible anyway.)
>
> spawn( fun () -> m:f(X1, ..., Xn) end)
^^
you probably mean fun() -> f(...), otherwise you'd have to export f
anyway!
> has the same effect as
> spawn(m, f, [X1, ..., Xn])
What you describe is not how it works today:
====================================
-module(t).
-export([t/0]).
t() ->
spawn(fun() -> loop() end).
loop() ->
receive
ok ->
loop()
end.
====================================
1> c(t).
{ok,t}
2> P = t:t().
<0.32.0>
3> process_info(P, current_function).
{current_function,{t,loop,0}}
4> l(t).
{module,t}
5> process_info(P, current_function).
{current_function,{t,loop,0}}
6> l(t).
{module,t}
7> process_info(P, current_function).
undefined
> > Use funs with care.
>
> Yes that is certainly true.
> But as Richard wrote there are several advantages of using funs over a
> tuple, and I can see no real advantage of using the tuple approach.
> Correct behaviour for code change can just as easily be achieved with funs
> as with "apply tuple"; you just need to think about it in a new way.
I still disagree. A scheme in which code change is achieved by
uncontrolled crashes is not really what we're looking for. If you can
find a way to change code of funs in a real, distributed system,
please let us know!!
Just to make my point clear, I do like funs, and I use them all the
time, but only for short-lived tasks like in a local lists:foreach
etc. In code that e.g. registers callbacks to be invoked at a later
time, I use the tuple syntax.
/martin
More information about the erlang-questions
mailing list