The following exercise demonstrates the difficulty in using cuts with tabling.
:- table cut_p/1, cut_q/1, cut_r/0, cut_s/0. cut_p(X) :- cut_q(X), cut_r. cut_r :- cut_s. cut_s :- cut_q(_). cut_q(1). cut_q(2). once(Term) :- call(Term), !.What solutions are derived for the goal ?- cut_p(X)? Suppose that cut_p/1 were rewritten as
cut_p(X) :- cut_q(X), once(cut_r).How should this cut over a table affect the answers generated for cut_p/1? What happens if you rewrite cut_p/1 in this way and compile it in XSB?
In Exercise 5.2.6, cut_p(1) and cut_p(2) should both be true. Thus, the cut in the literal once(cut_r) in the revised program may inadvertently cut away solutions that are demanded by cut_p/1. Version 2.5 of XSB does not allow cuts over tabled predicates. XSB checks whether a tabled predicate statically lies in the scope of a cut at compile time. If so, the compilation is aborted5.3. At runtime, it also ensures that no incomplete tables are cut over whenever it executes a cut.
However, cuts are allowed within tabled predicates, subject (as always) to the restriction that the scope of a cut cannot include a call to a tabled predicate.
:- table demo/1. demo(true). demo((A,B)) :- !, demo(A), demo(B). demo(C) :- call(C).More elaborate tabled meta-interpreters can be extremely useful, for instance to implement various extensions of definite or normal programs.
In Version 2.5 of XSB a ``cut'' over tables occurs only when the user makes a call to a tabled predicate from the interpreter level, but does not generate all solutions. In such a case, the user will see the warning "Removing incomplete tables..." appear. Any complete tables will not be removed. They can be abolished by using one of XSB's predicates for abolishing tables.