% Slices are an important data type in Prolog, giving
% a more powerful interface to sequences than lists.
% Unlike lists, slices are typed only by the
% elements they contain (not the number of elements).
% An uninitialized slice equals to an empty list and has
% length 0.
empty_slice(S) :-
S = [],
length(S, 0).
main :-
empty_slice(S),
writeln('uninit:'),
write(S), write(' '), write(S == []), write(' '), writeln(length(S, 0)),
% To create an empty slice with non-zero length, use
% the builtin `length/2`. Here we make a slice of
% atoms of length 3 (initially uninstantiated).
length(S1, 3),
writeln('emp:'),
write(S1), write(' len: '), length(S1, Len), write(Len),
% We can set and get just like with lists.
S2 = [a, b, c],
writeln('set:'), writeln(S2),
nth0(2, S2, Element),
write('get: '), writeln(Element),
% `length/2` returns the length of the slice as expected.
length(S2, L),
write('len: '), writeln(L),
% In addition to these basic operations, slices
% support several more that make them richer than
% lists. One is the append/3 predicate, which
% returns a slice containing one or more new values.
append(S2, [d], S3),
append(S3, [e, f], S4),
write('apd: '), writeln(S4),
% Slices can also be copied. Here we create a new
% slice C of the same length as S4 and copy into C from S4.
length(C, L),
append(C, [], S4),
write('cpy: '), writeln(C),
% Slices support a "slice" operator with the syntax
% slice(List, Start, End, Slice).
slice(S4, 2, 5, L1),
write('sl1: '), writeln(L1),
% This slices up to (but excluding) the 5th element.
slice(S4, 0, 5, L2),
write('sl2: '), writeln(L2),
% And this slices up from (and including) the 3rd element.
slice(S4, 2, L, L3),
write('sl3: '), writeln(L3),
% We can declare and initialize a variable for slice
% in a single line as well.
T = [g, h, i],
write('dcl: '), writeln(T),
% Prolog has built-in predicates for list operations.
T2 = [g, h, i],
(T == T2 ->
writeln('T == T2')
;
writeln('T \== T2')
),
% Slices can be composed into multi-dimensional data
% structures. The length of the inner slices can
% vary, unlike with multi-dimensional arrays.
TwoD = [
[0],
[1, 2],
[2, 3, 4]
],
write('2d: '), writeln(TwoD).
% Helper predicate to slice a list
slice(List, Start, End, Slice) :-
length(List, Len),
(End > Len -> EndIndex = Len ; EndIndex = End),
sublist(List, Start, EndIndex, Slice).
sublist(List, Start, End, Slice) :-
length(Before, Start),
length(Slice, Length),
Length is End - Start,
append(Before, Rest, List),
append(Slice, _, Rest).