Попробуйте это, используя сокращение (!) после 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([]).
Работает нормально, но не реентерабельно, второй результат запроса неверен:
?- 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]].
Предупреждение. Пролог-система с логической семантикой обновления
может быть неэффективной при повторном выполнении retract/1.
person
Mostowski Collapse
schedule
08.11.2020
assertz
вместоassert
решит это загадочное несоответствие. - person Eugene Sh.   schedule 23.03.2015assert
иassertz
делают одно и то же. :) - person lurker   schedule 23.03.2015assert/1
устарел в пользуassertz/1
. Я не знаю, почему это не будет последовательно. Я все еще жду, пока ОП объяснит, что несовместимо. :) - person lurker   schedule 23.03.2015