Reusing predicate name across modules

With use_module/1, it’s possible to refer to the imported predicates using the module name as prefix, as in module_name:predicate. This implies that I should be able to reuse predicate names across modules without clashes. However, that is not what I am seeing.

How can I import predicates from both modules without running into the error below? In theory, the two predicates can be referenced as m1:hello and m2:hello, and there needn’t be a name clash as long as we don’t try using the unqualified name.

Why it’s important to be able to reuse predicate names across modules: because that’s the promise of modules as I understand it. Otherwise, I can just do without modules and manage my predicate names manually across the entire program.

% m1.pl
:- module(m1, [hello/0]).
hello :- writeln('hello from m1').

% m2.pl
:- module(m2, [hello/0]).
hello :- writeln('hello from m2').

% m3.pl
:- module(m3, []).
:- use_module(m1).
:- use_module(m2).
run :- m1:hello.

This gives an error:

ERROR: m3.pl:3:
ERROR:    import/1: No permission to import m2:hello/0 into m3 (already imported from m1)

I believe that error is happening because use_module/1 implicitly puts all the exported predicates into the importing modules. If you use use_module/2 with an empty import list, then it should work as intended.

:- module(m3, []).
:- use_module(m1, []).
:- use_module(m2, []).
run :- m1:hello.

Amazing, thank you!

1 Like