Tudor's solution is good. However, I have come to see the benefits of using conditional statements where appropriate, even though I find the aesthetics a bit lacking, so I would suggest this solution instead:
remove_duplicates([], []).
remove_duplicates([H|T], R) :-
( memberchk(H,T)
-> remove_duplicates(T, R)
; remove_duplicates(T, R0),
R = [H|R0]
).
An explicit conditional like this does not create a spurious choice point. It's that choice point which is causing Tudor's solution to require a negated member/2
, which you were trying to correct with a cut. So even though it looks less beautiful, it's a somewhat more efficient solution.
Also, using memberchk/2
instead of member/2
is a small optimization for cases where you do not require member/2
's ability to generate solutions. Compare:
?- time(remove_duplicates([a,b,a,b,b,c], I)).
% 14 inferences, 0.000 CPU in 0.000 seconds (96% CPU, 1037114 Lips)
I = [a, b, c].
to Tudor's revision of your code:
?- time(remove_duplicates([a,b,a,b,b,c], I)).
% 28 inferences, 0.000 CPU in 0.000 seconds (94% CPU, 2264822 Lips)
I = [a, b, c] ;
% 28 inferences, 0.000 CPU in 0.000 seconds (92% CPU, 1338752 Lips)
I = [a, b, c] ;
% 15 inferences, 0.000 CPU in 0.000 seconds (88% CPU, 1065341 Lips)
false.