Consider the procedure foo/0 defined by
:- dynamic foo/0.
foo :- assertz(foo), fail.
Each call to foo/0 asserts a new last clause for foo/0. After
the Nth call to foo/0 there will be N+1 clauses for foo/0.
When foo/0 is first called, a
virtual copy of the procedure is made, effectively freezing the definition
of foo/0 for that call. At the time of the call,
foo/0 has exactly one clause. Thus, when
fail/0 forces backtracking, the call to foo/0 simply fails:
it finds no alternatives. For example,
| ?- compile(user).
| :- dynamic foo/0.
| foo :- assertz(foo), fail.
| ^D
% user compiled in module user, 0.100 sec 2.56 bytes
yes
| ?- foo. % The asserted clause is not found
no
| ?- foo. % A later call does find it, however
yes
| ?-
Even though the virtual copy of foo/0 being run by the first call is
not changed by the assertion, the Prolog database is. Thus, when a
second call to foo/0 is made, the virtual copy for that call
contains two clauses. The first clause fails, but on backtracking
the second clause is found and the call succeeds.