[erlang-questions] Overriding built-in functions in a module

Richard O'Keefe <>
Wed Jun 9 03:53:29 CEST 2010


On Jun 4, 2010, at 6:25 PM, Raimo Niskanen wrote:
>>> This was a little bit unrelated to the topic. Given that you can't
>>> call a non-exported function with that syntax, that code is  
>>> certainly
>>> not calling the local fun spawn/1, since it's not exported.
>>
>> Note that I wasn't suggesting that the call should be *allowed*,
>> only that it is *there*.  There's a big difference between
>> "there are NO calls to this function" and
>
> But there *are* no calls to the local function spawn/1.

Yes there is, it's just not a *local* call.
>
> The local function spawn/1 will never be used and
> that is what that warning says.

No it isn't, really.  If the error message said
	There is a remote call to local function spawn/1
	but it is not exported so it can never be used
	that way.
I might agree with you.

Just to repeat the context, imagine
	-module(foo).
	-export([bah/1]).
	bar(X) -> [X].
./foo.erl:2: function bah/1 undefined
./foo.erl:3: Warning: function bar/1 is unused

The mistake here isn't that bar/1 isn't used, but that
it's not *exported*.  We can see this even more clearly
if we change the example:

      1  -module(foo).
      2  -export([bah/1]).
      3  bar(X) when X < 0 -> ugh(-X);
      4  bar(X) -> X+1.
      5  ugh(X) when X < 0 -> bar(-X);
      6  ugh(X) -> X-1.

      ./foo.erl:2: function bah/1 undefined
      ./foo.erl:3: Warning: function bar/1 is unused
      ./foo.erl:5: Warning: function ugh/1 is unused

This time there *is* a local function call to bar/1
and there *is* a local function call to ugh/1.  They
are both *used*.  What they aren't is *reachable*.

Now let's change the example one more time.

      1  -module(foo).
      2  -export([zoo/0]).
      3  bar(X) when X < 0 -> ugh(-X);
      4  bar(X) -> X+1.
      5  ugh(X) when X < 0 -> bar(-X);
      6  ugh(X) -> X-1.
      7  zoo() -> is_function(fun bar/1), is_function(fun ugh/1).

      ./foo.erl:7: Warning: the call to is_function/1 has no effect

The functions bar/1 and ugh/1 are no more reachable than before.
There is no possible call from the outside that will ever result in
either function being invoked.  But suddenly they are "used".

Judging from the outside, what we have is
   a function is reachable iff
   (1) it is exported or
   (2) there is a local call to it from a reachable function or
   (3) a 'fun f/n' term referring to it occurs in a reachable function.

A function can be *USED* fifty million times without being
reachable, and as a test case like the one above proved, a
function can be reachable without being used.

This means that the wording of the error message is misleading.

>> In short, I am not quarreling with the decision to report an
>> error here, only commenting that the error message is extremely
>> misleading.
>
> #1 is. #2 not really.

No, really.  Whether the error message in question occurs or not
has nothing to do with whether the function is used, only with
whether it is reachable.  If you get the error message, no amount
of adding *uses* will remove it, unless they happen to be reachable
ones.

The message "no exported function directly or indirectly mentions
f/n" would not be misleading.  Even better, it would draw the
programmer's attention to the probable cause: a missing -export.



More information about the erlang-questions mailing list