Here is a code solution which correctly handles non-ground variables. It takes pains to avoid unwanted choicepoints. I’m deliberately avoiding using if_ in reif package so that the code is easier to grok for beginners.
As with clumped/2, this is only preventing consecutive duplicates, hence its predicate name.
I prefer to use “ne” vs “eq” (not equal vs equal), to be more meaningful than the generic true vs false.
no_cons_dupes([], []).
no_cons_dupes([H|T], [H|R]) :-
no_cons_dupes_(T, H, R).
no_cons_dupes_([], _, []).
no_cons_dupes_([H|T], P, R) :-
( H \= P
% Certain mismatch
-> no_cons_dupes_eq_(ne, T, H, R)
; H == P
% Certain match
-> no_cons_dupes_eq_(eq, T, H, R)
% Unsure whether matches
; H = P,
no_cons_dupes_eq_(eq, T, H, R)
; dif(H, P),
no_cons_dupes_eq_(ne, T, H, R)
).
% "ne" means "not equal"
no_cons_dupes_eq_(ne, T, H, [H|R]) :-
no_cons_dupes_(T, H, R).
no_cons_dupes_eq_(eq, T, H, R) :-
no_cons_dupes_(T, H, R).
Example output:
?- no_cons_dupes([a, a, a, a, b, c, c, a, a, d, e, e, e, e], L).
L = [a, b, c, a, d, e].
This Prolog code has the advantage of being able to produce logical/sensible output when given uncertainty, e.g.:
?- no_cons_dupes([a, a, b, b, b, c, c, a], L).
L = [a, b, c, a].
?- no_cons_dupes([a, a, b, b, b, c, CV, a], L).
CV = c,
L = [a, b, c, a] ;
CV = a,
L = [a, b, c, a] ;
L = [a, b, c, CV, a],
dif(CV, c),
dif(CV, a).
?- no_cons_dupes([A, B, C], L).
A = B, B = C,
L = [C] ;
A = B,
L = [B, C],
dif(C, B) ;
B = C,
L = [A, C],
dif(C, A) ;
L = [A, B, C],
dif(B, A),
dif(C, B).