Short answer: cut/3 does not pop from the list if it finds an element.
The first answer L = []. is the result of the second clause firing. Now the next answer is generated by the last clause. So what happens is:
sublist(A,[1,2,3]) :- % C = [1,2,3]
cut([A|B],[1,2,3],[H|T]) :- % H = 1, T = [2,3], Z = [1,2,3]
A = H, % A=1
!.
sublist(B,[1,2,3]).
So since the second clause of cut/3 fires, the second and third argument are equivalent and thus cut/3 does not "pop" from the list.
A way to solve this and guarantee progression is popping from the list, with:
cut(_,[],[_|_]) :- false.
cut(H,[H|T],T) :-
!.
cut(X,[_|T],Y) :-
cut(X,T,Y).
(I also took the liberty to replace X with H in the head of the clause making it more elegant). Now it generates:
?- sublist(L,[1,2,3]).
L = [] ;
L = [1] ;
L = [1, 2] ;
L = [1, 2, 3] ;
false.
Note that the answer does not generate all lists: for instance L = [2,3] is also a valid answer. The reason this does not work is because cut/3 has ! and thus does not allow to introduce additional elements. You can solve this with:
cut(_,[],[_|_]) :- false.
cut(H,[H|T],T).
cut(X,[_|T],Y) :-
cut(X,T,Y).
Now we obtain:
?- sublist(L,[1,2,3]).
L = [] ;
L = [1] ;
L = [1, 2] ;
L = [1, 2, 3] ;
L = [1, 3] ;
L = [2] ;
L = [2, 3] ;
L = [3] ;
false.
Nevertheless you can solve the problem quite elegantly without using a help predicate at all. We can first construct a predicate that validates/creates lists:
list([]).
list([_|T]) :-
list(T).
Next we state that if X is empty, you do not really care what sort of list is at the right:
sublist([],L) :-
list(L).
And finally if X is not empty, we need to obtain HX (the head of X) somewhere. If we find it, we can either decide to "accept" it, and pop both lists, or we can decide to look for another HX, like:
sublist([HX|TX],[HX|TY]) :-
sublist(TX,TY).
sublist(X,[_|TY]) :-
X = [_|_],
sublist(X,TY).
The X = [_|_] in the last clause in not strictly necessary, but prevents generating duplicate results with the sublist([],X) clause.
Or putting it together:
list([]).
list([_|T]) :-
list(T).
sublist([],L) :-
list(L).
sublist([HX|TX],[HX|TY]) :-
sublist(TX,TY).
sublist(X,[_|TY]) :-
X = [_|_],
sublist(X,TY).
This generates:
?- sublist(L,[1,2,3]).
L = [] ;
L = [1] ;
L = [1, 2] ;
L = [1, 2, 3] ;
L = [1, 3] ;
L = [2] ;
L = [2, 3] ;
L = [3] ;
false.
Or:
?- sublist([1,2,3],L).
L = [1, 2, 3] ;
L = [1, 2, 3, _G2440] ;
L = [1, 2, 3, _G2440, _G2443] ;
L = [1, 2, 3, _G2440, _G2443, _G2446] ;
L = [1, 2, 3, _G2440, _G2443, _G2446, _G2449] ;
L = [1, 2, 3, _G2440, _G2443, _G2446, _G2449, _G2452] ;
L = [1, 2, 3, _G2440, _G2443, _G2446, _G2449, _G2452, _G2455] ;
L = [1, 2, 3, _G2440, _G2443, _G2446, _G2449, _G2452, _G2455|...] ;
Or:
?- sublist([1,2,3],[1,2,4,5,3,6]).
true ;
cut(_,[],[_|_]) :- false.Just its absence will cause queries that look likecut(_,[],[_|_]).to fail since it doesn't match a succeeding rule. And did you try doing atrace? Or did you try just testingcut/3itself? Is there a reason you're creatingcut/3and not just usingselect/3? - lurker