Doubt about funs
Richard Carlsson
richardc@REDACTED
Thu Feb 22 13:35:43 CET 2001
On 21 Feb 2001, Lon Willett wrote:
> 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.
It has been vaguely discussed (in the work on creating a Standard Erlang
specification), but then restricted to built-in functions only (since
these are known not to change), like `fun erlang:length/1'. It never
caught on, though, and I don't think it was a very useful idea.
After some more pondering about the problem of funs and code change, I
think that the main issue is the use of the `F(...)' syntax. A simple
rule should suffice here: if the callback value could be rather old, so
that its target module might have been replaced once or more since the
value was passed, then *do not use `F(...)' for the callback*.
If we write code for a server or similar long-lived process, allowing
clients to send us callbacks (in some form), then there are two possible
situations:
In the first case, we apply the callback as soon as we handle the
message in which it was passed. In this case, we can allow the client to
pass a fun which we apply using `F(...)', because we can assume that
there hae been no code change between its creation and its application.
(It is of course possible that the fun is already "stale" when sent to
us, but this is not really different from being sent a fun which is
broken in some other way.)
In the second case, we ourselves are storing the callback for later use.
We thus know that when we eventually apply it, the callback module could
have been replaced any number of times since we were passed the value.
In this case, we should probably not use `F(...)' (even when it would be
tempting). We should instead decide on a format for the callbacks, such
as `{hook, Module, FunctionName, Arity}', match out the components, and
call `Module:FunctionName(...)'. In this way, we are *sure* that we do
not crash the program by replacing client code (as long as the code
remains functionally compatible), because we avoid applying any given
fun-values that could have become stale *while we were storing them*.
Thus, I say: never use F = {M,N} when you are going to call F with
F(...) - and vice versa, if you *want* a dynamic call, do it by matching
out and calling M:F(...). For a function that takes a callback as
argument, either document that it should be a fun, *or* a tuple
representing a function name in some way, but do not allow both.
The details of how a dynamic call-back hook should look (e.g., should it
include arity and/or "user data"?) are probably best left for the
programmer to decide for his particular application. (Maybe for OTP to
standardize.) There might even be reason to include a syntax for it in
the language, but I don't have any really good suggestions right now.
/Richard
Richard Carlsson (richardc@REDACTED) (This space intentionally left blank.)
E-mail: Richard.Carlsson@REDACTED WWW: http://www.csd.uu.se/~richardc/
More information about the erlang-questions
mailing list