[erlang-questions] Overriding built-in functions in a module
Tue Jun 15 09:17:18 CEST 2010
Richard O'Keefe writes:
> On Jun 12, 2010, at 6:31 AM, Mikael Pettersson wrote:
> > Richard O'Keefe writes:
> >> Why? Suppose we have a module
> >> -module(foo).
> >> -export([bar/1]).
> >> bar(N) when N > 0 -> ?MODULE:bar(N-1);
> >> bar(0) -> 'DONG!'.
> >> In what sense is the call to ?MODULE:bar/1 a call to some *other*
> >> function than the bar/1 here before us?
> > Because in Erlang a call with both module and function names
> > supplied is a "remote" call, which always invokes the latest
> > version of the module whose name was given.
> No, the fact that a call is a remote call does NOT make it a
> call to a function OTHER THAN THE FUNCTION IT CALLS.
Er, that's obvious.
> In this example, the function that is called is foo:bar/1.
Yes. But foo:bar/1 is not necessarily the same code as the
"bar/1 here before us".
> > So if a process P
> > is executing code in version 1 of the module, a newer version
> > 2 of the module is loaded, and P calls ?MODULE:F(...), then
> > that call invokes F in version 2 of the module, not version 1.
> As the Spartans once put it, "if".
> If the module is *NOT* reloaded, which is, let's face it,
> *almost all the time*, then there is no intelligible criterion
> by which it could be called "some *other* function".
> Even if the module is reloaded, that is not SOME OTHER FUNCTION.
> It is still foo:bar/1.
Only the name/arity remains known. You can make no assumptions
about its behaviour, unless you known exactly ahead of time that
the replacement module is designed to do so.
Scheme has the same issue, since global functions are simply
variables bound to function closures, and it allows those
bindings to be altered with set!.
> When you talk about a newer version of module 'foo',
> you call it a newer version, not ANOTHER module.
> But when you talk about a newer version of foo:bar/1,
> suddenly it's an *other* function.
> Let's be consistent in the way we talk about things.
"new version" is for all intents and purposes "new/other code".
The Erlang language and its implementation places no(*) requirements
on newer versions of modules being compatible with older ones.
(Of course there are guidelines / design patterns that do so
for the sake of safe live updates, but that's not the issue here.)
(*) Maybe the newfangled type specs stuff could be considered
to add some such requirements, but even then you can't pretend
to know for a fact what code a remote call will invoke.
More information about the erlang-questions