For comparison purposes, the definition of the sublist/2
predicate used in the Logtalk library is:
sublist(List, List).
sublist(Sublist, [Head| Tail]) :-
sublist(Tail, Head, Sublist).
sublist(Sublist, _, Sublist).
sublist([Head| Tail], _, Sublist) :-
sublist(Tail, Head, Sublist).
sublist([Head| Tail], Element, [Element| Sublist]) :-
sublist(Tail, Head, Sublist).
IIRC, this is a common definition.Some sample calls could be:
?- list::sublist(Sublist, [1,2,3]).
Sublist = [1, 2, 3] ;
Sublist = [2, 3] ;
Sublist = [3] ;
Sublist = [] ;
Sublist = [2] ;
Sublist = [1, 3] ;
Sublist = [1] ;
Sublist = [1, 2].
?- list::sublist([1,2], List).
List = [1, 2] ;
List = [_1376, 1, 2] ;
List = [_1376, _1382, 1, 2] ;
List = [_1376, _1382, _1388, 1, 2] ;
...
?- list::sublist(Sublist, List).
Sublist = List ;
List = [_1172|Sublist] ;
List = [_1172, _1178|Sublist] ;
List = [_1172, _1178, _1184|Sublist] .
...
Update
Noticed that the definition in the question and the one in my answer don't have the same semantics. The definition in the question implies consecutive elements. E.g.
?- sublist(Sublist, [1,2,3]).
Sublist = [] ;
Sublist = [1] ;
Sublist = [1, 2] ;
Sublist = [1, 2, 3] ;
Sublist = [] ;
Sublist = [2] ;
Sublist = [2, 3] ;
Sublist = [] ;
Sublist = [3] ;
Sublist = [] ;
false.
One issue in this definition is that the empty list solution is generated multiple times.
conc(L1, L2, L)
is decomposing the list into two lists; your suggested implementation would therefore look likesublist(S, L) :- conc(_, S, L) ; conc(S, _, L).
If you look at the output of that implementation withsublist(S, [1,2,3,4])
, you'll notice[2,3]
is never generated, but instead you get all sublists starting with 1 and also all sublists ending with 4. – Daniel Lyons