Dynamic Prolog predicate with incrementing component

706 views Asked by At

I have a knowledge base consisting of a set of rules whose head of each rule performs assert or retract of complex terms when certain conditions occur.

How can I ensure that Id is incremented with each assert(term(Id,A,B,C))?

2

There are 2 answers

7
repeat On

Assuming you don't care about holes in the Id (which occur when retracting id_person/2 clauses) you could do:

:- dynamic nextID/1.
:- dynamic id_person/2.
nextID(0).

assertz_person(P) :-
   nextID(I),
   retract(nextID(I)),
   I1 is I+1,
   assertz(nextID(I1)),
   assertz(id_person(I,P)).

Sample use (works with SWI-Prolog 8.0.0 and SICStus Prolog 4.5.0):

?- id_person(I,P).
false.

?- assertz_person(joan), id_person(I,P).
I = 0, P = joan.

?- assertz_person(al), assertz_person(ian), id_person(I,P).
   I = 0, P = joan
;  I = 1, P = al
;  I = 2, P = ian.
0
Paulo Moura On

As you're asserting clauses for a term/3 predicate where the first argument is a unique (integer) identifier, there's no need for an auxiliary dynamic predicate to represent the current counter. You can simply do instead:

:- dynamic(term/3).

assert_term(A, B, C) :-
    (   term(Id, _, _, _) ->
        NextId is Id + 1
    ;   NextId is 1
    ),
    asserta(term(NextId, A, B, C)).

The call to asserta/1 will make the latest asserted clause for term/3 to be the first to be retrieved when called, as above, with all arguments unbound, thus providing access to the last count. This solution assumes, however, that the clauses are not being retracted arbitrarily.