Challenge 3: Why assertz Isn't Undone on Backtracking — Possible Solution ==================================================================== leak_demo.pl: :- dynamic(logged/1). log_and_fail(X) :- assertz(logged(X)), fail. Query: ?- log_and_fail(oops). false. ?- logged(X). X = oops. -- Explanation -- -- -- log_and_fail(oops) asserts logged(oops), then immediately calls -- fail/0, which forces Prolog to backtrack out of the whole clause -- -- the overall query itself reports false, exactly as if nothing had -- succeeded. But querying logged(X) afterward shows oops is still -- there. This is the key contrast: an ORDINARY variable binding made -- during a goal that later fails is automatically undone as part of -- backtracking -- if X had been bound to oops via unification alone, -- that binding would vanish the moment Prolog backtracked past it, -- leaving no trace. assertz is not a variable binding, though -- it's -- a genuine, permanent side effect on the database, and Prolog's -- backtracking mechanism has no way to "unassert" it automatically. -- Once asserted, a fact stays asserted regardless of what the calling -- goal eventually does, unless something explicitly retracts it. WHY THIS WORKS AS AN ANSWER ------------------------------ This builds a concrete goal that asserts a fact and then deliberately fails, showing the query itself reporting false while the asserted fact survives regardless -- directly contrasting assertz's permanent, not-undone-by-backtracking side effect against how an ordinary unification binding would have vanished under the same failure.