"logical update view" would be more correctly called "transactional update view"?
Having anything else would be just sub-par and impossible to reason about.
Note that retract/1 fails silently if the predicate is unknown:
?- retract(foo(a,b)). false. % Predicate is still unknown ?- predicate_property(foo(_,_),dynamic). false. ?- assert(foo(a,b)). true. % Predicate is now known and dynamic ?- predicate_property(foo(_,_),dynamic). true. % Retract fact ?- retract(foo(a,b)). true. % Fact is now gone! ?- retract(foo(a,b)). false.
A clause can be asserted multiple times (yes, they can!). In that case, retract/1 backtracks over the identical clauses:
?- assertz(foo(a,b)). true. ?- assertz(foo(a,b)). true. ?- bagof([X,Y],foo(X,Y),Bag). Bag = [[a, b], [a, b]]. ?- retract(foo(a,b)). true ; true. ?- retract(foo(a,b)). false.
Consider retractall/1.