I am struggling to find a way to use transactions to throw away side effect data from the failed choicepoints in a generator predicate. Here’s an example:
Let’s say I have multiple alternatives for a predicate called
noun/3. I want to backtrack over these until I find the right one. Unfortunately, each instance of noun/3 asserts a term. I only want to keep the asserts for proofs that succeed and throw away the others. Below is an example.
The problem is that, since I am calling the noun/3 generator inside the transaction/1 predicate, Prolog only does a “redo” on the generator term, and so the transaction doesn’t rollback, it just keeps collecting changes from the (failed) backtracking.
I think I’m looking for a way to transact each choicepoint generated by the predicate passed to transaction/1 independently, rolling back all data done by a choice point on redo (as opposed to the current transaction/1 predicate that puts them all in a single transaction).
…or some other way of doing this. Unfortunately changing the noun predicates to not side effect is a large rewrite…
findDogInstance(ID) :- transaction(( noun(dog, ID, Kind), Kind \== concept )). noun(dog, ID, concept) :- gensym(dog, ID), assert(test(ID, is, dog, concept)). noun(dog, ID, instance) :- gensym(dog, ID), assert(test(ID, is, dog, instance)). ?- findDogInstance(X). X = dog2. ?- test(X, Y, Z, A). % I don't want this one since it wasn't in the successful proof... X = dog1, Y = (is), Z = dog, A = concept ; % I do want this one X = dog2, Y = (is), Z = dog, A = instance. ~~