There is something about retract/1
that doesn't make sense to me.
According to ISO/IEC 13211-1:1995:
8.9.3 retract/1
8.9.3.1 Description
retract(Clause)
is true iff the database contains at least one dynamic procedure with a clauseClause
which unifies withHead :- Body
.Procedurally,
retract(Clause)
is executed as follows:a) If
Clause
unifies with':-'(Head, Body)
, then proceeds to 8.9.3.1 c,b) Else unifies
Head
withClause
andtrue
withBody
,c) Searches sequentially through each dynamic user-defined procedure in the database and creates a list L of all the terms
clause(H, B)
such that 1) the database contains a clause whose head can be converted to a termH
(7.6.3), and whose body can be converted to a termB
(7.6.4), and 2)H
unifies withHead
, and 3)B
unifies withBody
.d) If a non-empty list is found, then proceeds to 8.9.3.1 f,
e) Else the goal fails.
f) Chooses the first element of the list L, removes the clause corresponding to it from the database, and the goal succeeds.
g) If all the elements of list L have been chosen, then the goal fails.
h) Else chooses the first element of the list L which has not already been chosen, removes the clause, if it exists, corresponding to it from the database and the goal succeeds.
retract(Clause)
is re-executable. On backtracking, continue at 8.9.3.1 g. [...]
"If it exists"? How could it be that it does not exist anymore upon re-execution?
The database update semantics suggest that "it" always exists:
7.5.4 A logical database update
Any change in the database that occurs as a result of executing a goal (for example, when the activator of a subgoal is a call of
assertz/1
orretract/1
) shall affect only an activation whose execution begins afterwards. This change shall not affect any activation that is currently being executed.NOTE — Thus the database is frozen during the execution of a goal, and the list of clauses defining a predication is fixed at the moment of its execution (see 7.7.7 e).
Below, I tried using retract(f(3))
to make clause f(3)
vanish before the re-execution of a prior retract(f(X))
:
?- abolish(f/1), maplist(assertz,[f(1),f(2),f(3)]). true. % setup complete ?- retract(f(X)), ( X = 2 -> retract(f(3)) ; true ). X = 1 ; X = 2 ; X = 3. % <----------------^^^^^^^^^^^^^
... but, alas, I failed: SICStus Prolog, GNU Prolog and SWI-Prolog gave the same (above) answers.
So why use the phrase "if it exists" in this context? To me it's redundant. And puzzling... help please!