SWI Prolog: avoiding name clashes between builtin predicates and dynamic predicates

Viewed 57

I'm wondering if it is possible to define a dynamic predicate with the same name and arity as a builtin predicate inside a module. I was hoping it would be enough to hide the builtin predicates in my module using delete_import_module/2. Alas, that doesn't seem to work. For instance, I cannot create a clause for halt/1 inside module foo:

?- delete_import_module(foo, user).
true.

?- asserta(foo:halt(x)).
ERROR: No permission to modify static procedure `halt/1'
ERROR: In:
ERROR:   [10] assert(foo:halt(x))
ERROR:    [9] toplevel_call(user:user: ...) at /usr/lib64/swipl-8.4.1/boot/toplevel.pl:1117

It still seems to think I'm talking about system:halt/1 even though that's not even visible in foo. Why is that?

1 Answers

I have noticed that the problem goes away if I try to call the predicate before adding the clause:

?- delete_import_module(foo, user).
true.

?- foo:halt(_).
Correct to: "system:halt(_)"? no
ERROR: Unknown procedure: foo:halt/1
ERROR:   However, there are definitions for:
ERROR:         halt/0
ERROR: 
ERROR: In:
ERROR:   [10] foo:halt(_20078)
ERROR:    [9] toplevel_call(user:foo: ...) at /usr/lib64/swipl-8.4.1/boot/toplevel.pl:1117
   Exception: (10) foo:halt(_8960) ? no debug
?- assert(foo:halt(_)).
true.

?- @(listing, foo).

:- dynamic halt/1.

halt(_).
true.

I've also tried poking the predicate in other ways (using current_predicate/1 and clause/2), but that doesn't have the same effect.

So while this does solve the problem, I still wonder what is going on here. Is this a bug? I'm using SWI Prolog 8.4.1 on Fedora Linux.

Related