Closures across module reloads, undocumented behavior?

Nahuel Greco <>
Thu Jul 29 17:42:02 CEST 2010


I found an strange behavior, probably undocumented:

1- Load a 'm' module (first version).
2- Start a process P1 whose initial function is m:a/1, this function
creates a closure that calls m:version/0 directly (not fully
qualified).
3- The closure is executed once, shows it calls the first version of
m:version/0, and is keep in memory by P1.
4- The source code of m is modified, m is compiled and the new version
is loaded.

Now, the strange thing is:

5- The same closure instance of step 3 is executed again by P1, but
what version of m:version/0 is called _depends on the changes_ made in
step 4. Also, I found you can change the bound values of the closure.

Detailing (see attached files):

Test 2:
- step 4: the m:version/0 function body is changed.
- step 5: then the closure will use the _NEW_ version of m:version/0.

Test 3:
- step 4: the name of m:version/0 is redefined to m:another_version/0,
and the closure body is redefined to call another_version/0.
- step 5: then the closure will call the _OLD_ version of m:version/0.

Test 4:
- step 4: a literal is changed inside the closure body.
- step 5: then the closure will use the _OLD_ version of m:version/0.

Test 5:
- step 4: the value bound from the closure is changed
- step 5: then closure will use the _NEW_ version of m:/version/0 with
the _NEW_ value.

I don't find a clear semantic and I didn't found any documentation
about this. What are the defined semantics for closures across module
reloads?

I'm attaching a test.erl file, it compiles and loads/reloads the many
versions of 'm', executing the tests 2-5 detailed before. The original
m version loaded in step 1 is m__base.erl and the one loaded in step 4
is m__[2-5].erl.

Output:

Erlang R13B04 (erts-5.7.5) [source] [smp:2:2] [rq:2] [async-threads:0]
[kernel-poll:false]
Eshell V5.7.5  (abort with ^G)
1> c(test).
{ok,test}
2> test:start().

- Unloading m old and current
- Loading m__base and starting process
Started a() from version 1
>From closure, version() -> 1, B -> first
- Loaded m__2 , differences with base: Increments the version
- Continuing process
>From closure, version() -> 2, B -> first

- Unloading m old and current
- Loading m__base and starting process
Started a() from version 1
>From closure, version() -> 1, B -> first
- Loaded m__3 , differences with base: Increments the version,
version/0 changed to another_version/0
- Continuing process
>From closure, version() -> 1, B -> first

- Unloading m old and current
- Loading m__base and starting process
Started a() from version 1
>From closure, version() -> 1, B -> first
- Loaded m__4 , differences with base: Increments the version, changed
text literal in closure
- Continuing process
>From closure, version() -> 1, B -> first

- Unloading m old and current
- Loading m__base and starting process
Started a() from version 1
>From closure, version() -> 1, B -> first
- Loaded m__5 , differences with base: Increments the version, changed
B assigned atom to 'second'
- Continuing process
>From closure, version() -> 2, B -> second
[undef,undef,undef,undef]
3>


Saludos,
Nahuel Greco.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: test.erl
Type: application/octet-stream
Size: 873 bytes
Desc: not available
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20100729/91471862/attachment.obj>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: m__base.erl
Type: application/octet-stream
Size: 409 bytes
Desc: not available
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20100729/91471862/attachment-0001.obj>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: m__2.erl
Type: application/octet-stream
Size: 391 bytes
Desc: not available
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20100729/91471862/attachment-0002.obj>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: m__3.erl
Type: application/octet-stream
Size: 456 bytes
Desc: not available
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20100729/91471862/attachment-0003.obj>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: m__4.erl
Type: application/octet-stream
Size: 437 bytes
Desc: not available
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20100729/91471862/attachment-0004.obj>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: m__5.erl
Type: application/octet-stream
Size: 425 bytes
Desc: not available
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20100729/91471862/attachment-0005.obj>


More information about the erlang-questions mailing list