ciao-lang / ciao

Ciao is a modern Prolog implementation that builds up from a logic-based simple kernel designed to be portable, extensible, and modular.
https://ciao-lang.org
GNU Lesser General Public License v3.0
268 stars 20 forks source link

(playground) use module import of overridden predicate #61

Closed Jean-Luc-Picard-2021 closed 2 years ago

Jean-Luc-Picard-2021 commented 2 years ago

While trying to port:

fCube: an efficient prover for Intuitionistic propositional Logic in Rextester - Vidal-Rosset, 2022 https://rextester.com/SEOO25214

I was running into a predicate lookup problem. I tried the following:

tab(X) :- Y is X, io_basic:tab(Y).

But the top-level cannot resolved the overridden tab/1:

?- tab(2*3+1).
{ERROR: No handle found for thrown exception 
error(type_error(integer,2*3+1),'io_basic:tab'/1-1)}

This works in other Prolog systems that have a module system.

mherme commented 2 years ago

Yes, you can do it no problem:

:- module(foo,[main/0,tab/1]).

main :- 
    tab(4),
    write(a).

tab(X) :- Y is X, io_basic:tab(Y).

and now:

?- use_module('/draft.pl').
{Compiling /draft.pl
WARNING: (lns 2-5) Unqualified predicate call to tab/1 assumed to local version, calls to predicate imported from io_basic must be qualified
}
yes
?- draft:tab(3+2), write(a).
     a
yes

If you want to avoid the warning when compiling the module you can do:

:- module(foo,[main/0,tab/1]).

main :- 
    foo:tab(4),
    write(a).

tab(X) :- Y is X, io_basic:tab(Y).

or use use :- redefining(tab/1).

:- module(_,[main/0,tab/1]).

main :- 
    tab(4),
    write(a).

:- redefining(tab/1).

tab(X) :- Y is X, io_basic:tab(Y).

In the top level:

?- use_module('/draft.pl').

yes
?- draft:tab(3+2), write(a).
     a
yes
jfmc commented 2 years ago

Note that predicates are never overridden, so the problem may be in the predicate visibility rules.

:- module(a, [foo/1]).
foo(a).
:- module(b, [foo/1]).
foo(b).
?- use_module(a).

yes
?- foo(X).

X = a ? 

yes
?- use_module(b).

yes
?- foo(X).

X = a ? 

yes

As @mherme says both a:foo(X) and b:foo(X) work, but module visibility rules in Ciao resolves foo(X) as a:foo(X). Perhaps b:foo(X) would be more natural? Changing it is not trivial but can do it, specially if this is expected in other languages.

Jean-Luc-Picard-2021 commented 2 years ago

With Novacore and Liblets its not needed anymore. Can put into swi/core.pl to make it run elsewhere.

jfmc commented 2 years ago

OK. I'll mark this as 'wontfix' and cite from another issue.