[Simple] These sources are equivalent?



This is a simple list exercise, solved in different ways:

Assuming these simple proposition:

member(X, [X|_]).
member(X, [_|R]) :- member(X,R).
nonmember(X,L) :- member(X,L), !, fail ; true.

We want to write a proposition to make a list composed by every member of L1
not member of L2.

Ex:
diff([1,2,3,4,5],[2,3],L3).
L3=[1,4,5]
yes

Teacher Schoolnotes Original Solution:
diff([],_,[]).

diff([T1|C1],L2,L3) :- member(T1,L2), diff(C1,L2,L3).

diff([T1|C1],L2,[T1|C3]) :- diff(C1,L2,C3).

Problem occurred:
First answer was correct but if refused it unified L3 progressively to any
list containing every member of L1 even if member of L2 producing wrong
answer.

Ex:
diff([1,2,3,4,5],[2,3],L3).
L3=[1,4,5]; --> correct
L3=[1,2,4,5]; --> wrong
L3=[1,3,4,5];
L3=[1,2,3,4,5];
no


Schoolnotes Solution, corrected by me:
diff([],_,[]).

diff([T1|C1],L2,L3) :- member(T1,L2), diff(C1,L2,L3).

diff([T1|C1],L2,[T1|C3]) :- nonmember(T1,L2), diff(C1,L2,C3).

It seem to work

My personal solution:
diff2(A,B,C) :- findall(X, (member(X,A), nonmember(X,B)) ,C).

It seem to work

My questions:

Which is the best solution?
Is the fact that the second and third solution use the operator ! bad?
Is possible to write that program without using negation (not, !)?



.