A trivial, roundabout way to do this:
?- setof(M, ( member(M, L1), \+ member(M, L2) ), Ms).
what exactly:
Make a set of all M such that M is a member of L1 but not a member of L2 .
?- L1 = [a,b,c,d,e,f,g], L2 = [c,f,x,y], setof(M, ( member(M, L1), \+ member(M, L2) ), Ms). Ms = [a, b, d, e, g].
If you do not want to create an ordered set, you can use bagof/3 instead of setof/3 :
?- L1 = [c,b,a,c,b,a], L2 = [c,y], setof(M, ( member(M, L1), \+ member(M, L2) ), Ms). Ms = [a, b]. ?- L1 = [c,b,a,c,b,a], L2 = [c,y], bagof(M, ( member(M, L1), \+ member(M, L2) ), Ms). Ms = [b, a, b, a].
However, the answer by @mat shows a more logical way of expressing "an item is not in the list" than \+ member(M, L2) .
There are also library predicates that would do the job. Another effective way to work with sets is to present them as sorted lists without duplicates, as in library(ordsets) :
?- L1 = [a,b,c,d,e,f,g,a,a,a], L2 = [c,f,x,y], time(setof(M, ( member(M, L1), \+ member(M, L2) ), Ms)). % 85 inferences, 0.000 CPU in 0.000 seconds (95% CPU, 1841262 Lips) Ms = [a, b, d, e, g]. ?- L1 = [a,b,c,d,e,f,g,a,a,a], L2 = [c,f,x,y], time(( sort(L1, S1), sort(L2, S2), ord_subtract(S1, S2, S) )). % 28 inferences, 0.000 CPU in 0.000 seconds (90% CPU, 1066545 Lips) S1 = [a, b, c, d, e, f, g], S = [a, b, d, e, g].
(In general, fewer conclusions mean less work done to prove the request. However, this is a little misleading when sort/2 involved, as it is always counted as one output. In SWI-Prolog, it uses the built-in C implementation, and it's hard to compare with pure Prolog code. Also keep in mind that setof/3 uses sort/2 internally.)