This is a combination of getref/2 and setref/2, behaving like
swapref(Name, OldValue, NewValue) :- getref(Name, OldValue), setref(Name, NewValue).Note that NewValue can be instantiated (or further instantiated) _after_ the reference has been set to refer to it. Therefore it is possible to use OldValue in the construction of NewValue.
% Example: a backtrackable counter :- local reference(ctr, 0). incref(Name) :- swapref(Name, Old, New), New is Old+1. ?- incref(ctr), incref(ctr), getref(ctr, C). C = 2 Yes (0.00s cpu) ?- incref(ctr), incref(ctr), fail ; getref(ctr, C). C = 0 Yes (0.00s cpu) % Example: a backtrackable term stack :- local reference(stack, []). push(Name, X) :- swapref(Name, Xs, [X|Xs]). pop(Name, X) :- swapref(Name, [X|Xs], Xs). top(Name, X) :- getref(Name, [X|_]). ?- push(stack, a), push(stack, b), getref(stack, Xs). Xs = [b, a] Yes (0.00s cpu) ?- push(stack, a), push(stack, b), pop(stack, X), getref(stack, Xs). X = b Xs = [a] Yes (0.00s cpu) ?- (push(stack, a) ; push(stack, b)), getref(stack, Xs). Xs = [a] Yes (0.00s cpu, solution 1, maybe more) Xs = [b] Yes (0.00s cpu, solution 2)