Strange behaviour of global variables with modules


Consider this minimal example:

In a file, define a minimal module:

:- module(mymodule, [counter_display/0]).

:- initialization((nb_setval(counter, 0), write('init done.'), nl)).

counter_display :-
    nb_getval(counter, V),
    format('counter value: ~w~n', [V]).

Then define in file as:

:- use_module(mymodule).

main :-

Then compile (C-c C-b in the builtin emacs, or [main] at prolog prompt).
In the console, you can see the init done. message, thus we know that the initialize/1 directive in the module has been executed.

but if you submit the goal main, here is what happens:

?- main.
ERROR: variable `counter' does not exist
ERROR:   [14] nb_getval(counter,_48952)
ERROR:   [13] mymodule:counter_display at /home/wurbel/src/prolog/tests/modules_and_main/
ERROR:   [11] toplevel_call(user:user:main) at /usr/lib/swipl/boot/
ERROR: Note: some frames are missing due to last-call optimization.
ERROR: Re-run your program in debug mode (:- debug.) to get more detail.

The documentation stipulates that global variables are scoped globally, so what am I missing here ?

Thank you in advance.


I forgot to mention : swi-prolog version is 9.1.21

The problem is not modules. Global variables are (unfortunately) unaware of modules. The problem is in threads. The editor runs in its own thread (named pce) and variables set there are not visible in any other thread.

Using global variables in threaded programs means you need some other way to initialize then a directive. Typically you initialize lazily or on demand using the exception/3 hook.

Thank you for the answer. This was the first time I initialized global variable with this method, which unfortunately is a bad idea !


Well, if you do not use threads and you do not load the code through the built-in editor (or the Emacs sweep mode, which also uses threads), initializing using a directive is fine. If you use threads, you need to realize that global variables are a per-thread feature, i.e., it is not only the value that is thread-specific, but also the existence and every thread starts without any global variables.

Yes of course, when not using the builtin editor or sweep everything is fine, but in a development phase I usually work from the editor (not with sweep unfortunately, as it cripples my emacs configuration when ran for about 15-20mn, I did not take the time to pinpoint the exact problem, but that’s another story !).

By the way, I will be aware of this thread locality in the future.

Thanks again.