これを試してみてください。retract/1 の後にカット (!) を実行し、明示的に assertz/1 をアサートします。
solutions(A,T,_) :-
T,
assertz(temp(A)),
fail.
solutions(_,_,S) :-
obtain(S).
obtain([A|S]) :-
retract(temp(A)), !,
obtain(S).
obtain([]).
正常に動作しますが、再入可能ではありません。2 番目のクエリ結果は間違っています。
?- solutions(X,between(1,3,X),L).
L = [1, 2, 3].
?- solutions(X-R,(between(1,3,X),solutions(Y,between(1,X,Y),R)),L).
L = [3-[2-[1-[1], 1, 2], 1, 2, 3]].
編集 08.11.2020:
gensym/2 を使用したリエントラント ソリューションは次のとおりです。
solutions(A,T,L) :-
setup_call_cleanup(
gensym('bag',B),
solutions(B,A,T,L),
retractall(temp(B,_))).
solutions(B,A,T,_) :-
T,
assertz(temp(B,A)),
fail.
solutions(B,_,_,S) :-
obtain(B,S).
obtain(B,[A|S]) :-
retract(temp(B,A)), !,
obtain(B,S).
obtain(_,[]).
両方のクエリが正常に機能するようになりました。
?- solutions(X,between(1,3,X),L).
L = [1, 2, 3].
?- solutions(X-R,(between(1,3,X),solutions(Y,between(1,X,Y),R)),L).
L = [1-[1], 2-[1, 2], 3-[1, 2, 3]].
警告:論理的な更新セマンティクスを備えた Prolog システムは、
retract/1 を繰り返し実行すると非効率になる可能性があります。