[erlang-bugs] Local vs external funs

Matthew Dempsky <>
Mon Jun 18 23:34:54 CEST 2007


The erlang module's documentation states "When a local fun is called,
the same version of the code that created the fun will be called (even
if newer version of the module has been loaded)."

Below is a module, bar.erl.  Calling bar:start() spawns a process that
repeatedly calls bar:foo/1 via different mechanisms.

Save this to bar.erl, and in erl run "c(foo), bar:start()".  The
process will print
    old foo (local indirectly)
    old foo (local indirectly with temporary)
    old foo (local indirectly from start)
    old foo (external directly)
    old foo (external indirectly)
    old foo (external indirectly with temporary)
    old foo (external from start)

Now edit bar.erl and change VER's definition from "old" to "new", and
run c(bar) in the shell.  The process will now start printing
    old loop
    old foo (local directly)
    old foo (local indirectly)
    new foo (local indirectly with temporary)
    new foo (local indirectly from start)
    new foo (external directly)
    new foo (external indirectly)
    new foo (external indirectly with temporary)
    new foo (external from start)

All of these behave as I expect, except for the "local indirectly with
temporary" and "local indirectly from start" cases.  My understanding
of the documentation is that both of these should have printed "old
foo" instead of "new foo".  This seems further supported by the fact
that "(fun foo/1)(...)" is optimized to the same assembly as
"foo(...)", which behaves differently than "X = fun foo/1, X(...)".

-module(bar).
-export([start/0, loop/2, foo/1]).

-define(VER, "old").

start() ->
    spawn_link(?MODULE, loop, [fun foo/1, fun ?MODULE:foo/1]).

loop(LocalFoo, ExternalFoo) ->
    io:format("~n" ++ ?VER ++ " loop~n"),

    foo("local directly"),
    (fun foo/1)("local indirectly"),
    X = fun foo/1, X("local indirectly with temporary"),
    LocalFoo("local indirectly from start"),

    ?MODULE:foo("external directly"),
    (fun ?MODULE:foo/1)("external indirectly"),
    Y = fun ?MODULE:foo/1, Y("external indirectly with temporary"),
    ExternalFoo("external from start"),

    timer:sleep(3000),
    loop(LocalFoo, ExternalFoo).

foo(How) ->
    io:format(?VER ++ " foo (~s)~n", [How]).



More information about the erlang-bugs mailing list