I had opened an issue on this but I don’t understand Jan’s response at all (sorry Jan), so I thought I will just repeat it in the group to hope for some enlightenment.
I will just repeat what I have verbatim, see at the end for an explanatory image.
The problem:
Calling a module-qualified predicate whose module has not been loaded yet causes a predicate with the same predicate indicator from unrelated (but autoloaded?) module to be called instead.
I can’t see a reason why this would be the case.
For example:
Take the original swipl module ${swipl_install_dir}/lib/swipl/library/prolog_pack.pl
which exports pack_install/1
.
Modify the code for pack_install/1
code by adding a format/2
line just to see what is being called:
pack_install(Spec) :-
format("***** Running original pack_install/1 ******"),
pack_default_options(Spec, Pack, [], Options),
pack_install(Pack, [pack(Pack)|Options]).
Copy prolog_pack.pl
it into a new my_prolog_pack.pl
(giving the module the name my_prolog_pack
in the module declaration, too). This module also exports pack_install/1
, modified as follows:
pack_install(Spec) :-
format("***** Running replacement pack_install/1 ******"),
pack_default_options(Spec, Pack, [], Options),
pack_install(Pack, [pack(Pack)|Options]).
Now start swipl and run:
?- pack_install('foo').
***** Running original pack_install/1 ******
So far so good. A default package is autoloaded and run.
Restart swipl and run a qualified predicate call, qualified with the name of a not-available module. The predicate in the library module is called instead:
?- my_prolog_pack:pack_install('foo').
***** Running original pack_install/1 ******
That’s at least unexpected. What I would expect is an exception telling me in no uncertain terms that my setup is foobared (as I say, it’s always better to get an solid exception & halt than to get good radiation dose from a suddenly differently specced Therac-25)
Loading the module used in the above qualification first now:
?- use_module('my_prolog_pack.pl').
true.
The the qualification works properly:
?- my_prolog_pack:pack_install('foo').
***** Running replacement pack_install/1 ******
% Contacting server at https://www.swi-prolog.org/pack/query ... done
Warning: No registered pack matches "foo"
false.
Good!
The default is now taken from the replacement pack:
?- pack_install('foo').
***** Running replacement pack_install/1 ******
% Contacting server at https://www.swi-prolog.org/pack/query ... done
Warning: No registered pack matches "foo"
false.
Also good.
However, a predicate qualified with prolog_pack
does not autoload the correct package and execute its predicate, it executes the predicate from the replacement package:
?- prolog_pack:pack_install('foo').
***** Running replacement pack_install/1 ******
% Contacting server at https://www.swi-prolog.org/pack/query ... done
Warning: No registered pack matches "foo"
false.
Note that both packs cannot coexist:
?- use_module(library('prolog_pack.pl')).
ERROR: import/1: No permission to import prolog_pack:pack_url_file/2 into user (already imported from my_prolog_pack)
ERROR: import/1: No permission to import prolog_pack:pack_rebuild/1 into user (already imported from my_prolog_pack)
ERROR: import/1: No permission to import prolog_pack:pack_remove/1 into user (already imported from my_prolog_pack)
The above is quite a wall of text, so here is an image with the three scenarios, whereby
- I’m okay with the module resolution for the green “action boxes”.
- I’m not okay with the module resolution for the orange “action boxes”. I would have expected exceptions instead of freewheeling dynamical resolution. (Why have module qualifications if they can be ignored by the system?)