From: Adrián Arroyo Calle Date: Tue, 6 Dec 2022 12:19:10 +0000 (+0100) Subject: Compatible Doclog docs for library(lists) X-Git-Tag: v0.9.2~258^2 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=df4b56148f9c505cd170da8eb8b7cf35dfba823a;p=scryer-prolog.git Compatible Doclog docs for library(lists) --- diff --git a/src/lib/lists.pl b/src/lib/lists.pl index 4eb204b1..15d9afa0 100644 --- a/src/lib/lists.pl +++ b/src/lib/lists.pl @@ -1,3 +1,7 @@ +/** +List manipulation predicates +*/ + :- module(lists, [member/2, select/3, append/2, append/3, foldl/4, foldl/5, memberchk/2, reverse/2, length/2, maplist/2, maplist/3, maplist/4, maplist/5, maplist/6, @@ -57,6 +61,18 @@ resource_error(Resource, Context) :- throw(error(resource_error(Resource), Context)). +%% length(?Xs, ?N). +% +% Relates a list to its length (number of items). It can be used to count the elements of a current list or +% to create a list full of free variables with N length. +% +% ?- length([a,b,c], 3). +% true. +% ?- length([a,b,c], N). +% N = 3. +% ?- length(Xs, 3). +% Xs = [_A, _B, _C]. + length(Xs0, N) :- '$skip_max_list'(M, N, Xs0,Xs), !, @@ -95,28 +111,61 @@ length_addendum([_|Xs], N, M) :- M1 is M + 1, length_addendum(Xs, N, M1). - +%% member(?X, ?Xs). +% +% Succeeds when X unifies with an item of the list Xs, which can be at any position. +% +% ?- member(X, "hello world"). +% X = h +% ; ... . +% member(X, [X|_]). member(X, [_|Xs]) :- member(X, Xs). - +%% select(X, Xs0, Xs1). +% +% Succeeds when the list Xs1 is the list Xs0 without the item X +% +% ?- select(c, "abcd", X). +% X = "abd". +% select(X, [X|Xs], Xs). select(X, [Y|Xs], [Y|Ys]) :- select(X, Xs, Ys). - +%% append(+XsXs, ?Xs). +% +% Concatenates a list of lists +% +% ?- append([[1, 2], [3]], Xs). +% Xs = [1, 2, 3]. +% append([], []). append([L0|Ls0], Ls) :- append(L0, Rest, Ls), append(Ls0, Rest). - +%% append(Xs0, Xs1, Xs). +% +% List Xs is the concatenation of Xs0 and Xs1 +% +% ?- append([1,2,3], [4,5,6], Xs). +% Xs = [1, 2, 3, 4, 5, 6]. +% append([], R, R). append([X|L], R, [X|S]) :- append(L, R, S). - +%% memberchk(?X, +Xs). +% +% This predicate is similar to member/2, but it only provides a single answer memberchk(X, Xs) :- member(X, Xs), !. - +%% reverse(?Xs, ?Ys). +% +% Xs is the Ys list in reverse order +% +% ?- reverse([1,2,3], [3,2,1]). +% true. +% reverse(Xs, Ys) :- ( nonvar(Xs) -> reverse(Xs, Ys, [], Xs) ; reverse(Ys, Xs, [], Ys) @@ -126,62 +175,111 @@ reverse([], [], YsRev, YsRev). reverse([_|Xs], [Y1|Ys], YsPreludeRev, Xss) :- reverse(Xs, Ys, [Y1|YsPreludeRev], Xss). +%% maplist(+Predicate, ?Xs0). +% +% This is a metapredicate that applies predicate to each element of the list Xs0 +% +% ?- maplist(write, [1,2,3]). +% 123 true. +% maplist(_, []). maplist(Cont1, [E1|E1s]) :- call(Cont1, E1), maplist(Cont1, E1s). +%% maplist(+Predicate, ?Xs0, ?Xs1). +% +% This is a metapredicate that applies predicate to each element of the lists Xs0 and Xs1. +% +% ?- maplist(length, ["hello", "prolog", "marseille"], Xs1). +% Xs1 = [5,6,9]. +% maplist(_, [], []). maplist(Cont2, [E1|E1s], [E2|E2s]) :- call(Cont2, E1, E2), maplist(Cont2, E1s, E2s). +%% maplist(+Predicate, ?Xs0, ?Xs1, ?Xs2). +% +% This is a metapredicate that applies predicate to each element of the lists Xs0, Xs1 and Xs2. maplist(_, [], [], []). maplist(Cont3, [E1|E1s], [E2|E2s], [E3|E3s]) :- call(Cont3, E1, E2, E3), maplist(Cont3, E1s, E2s, E3s). +%% maplist(+Predicate, ?Xs0, ?Xs1, ?Xs2, ?Xs3). +% +% This is a metapredicate that applies predicate to each element of the lists Xs0, Xs1, Xs2 and Xs3. maplist(_, [], [], [], []). maplist(Cont, [E1|E1s], [E2|E2s], [E3|E3s], [E4|E4s]) :- call(Cont, E1, E2, E3, E4), maplist(Cont, E1s, E2s, E3s, E4s). - +%% maplist(+Predicate, ?Xs0, ?Xs1, ?Xs2, ?Xs3, ?Xs4). +% +% This is a metapredicate that applies predicate to each element of the lists Xs0, Xs1, Xs2, Xs3 and Xs4. maplist(_, [], [], [], [], []). maplist(Cont, [E1|E1s], [E2|E2s], [E3|E3s], [E4|E4s], [E5|E5s]) :- call(Cont, E1, E2, E3, E4, E5), maplist(Cont, E1s, E2s, E3s, E4s, E5s). - +%% maplist(+Predicate, ?Xs0, ?Xs1, ?Xs2, ?Xs3, ?Xs4, ?Xs5). +% +% This is a metapredicate that applies predicate to each element of the lists Xs0, Xs1, Xs2, Xs3, Xs4 and Xs5. maplist(_, [], [], [], [], [], []). maplist(Cont, [E1|E1s], [E2|E2s], [E3|E3s], [E4|E4s], [E5|E5s], [E6|E6s]) :- call(Cont, E1, E2, E3, E4, E5, E6), maplist(Cont, E1s, E2s, E3s, E4s, E5s, E6s). - +%% maplist(+Predicate, ?Xs0, ?Xs1, ?Xs2, ?Xs3, ?Xs4, ?Xs5, ?Xs6). +% +% This is a metapredicate that applies predicate to each element of the lists Xs0, Xs1, Xs2, Xs3, Xs4, Xs5 and Xs6. maplist(_, [], [], [], [], [], [], []). maplist(Cont, [E1|E1s], [E2|E2s], [E3|E3s], [E4|E4s], [E5|E5s], [E6|E6s], [E7|E7s]) :- call(Cont, E1, E2, E3, E4, E5, E6, E7), maplist(Cont, E1s, E2s, E3s, E4s, E5s, E6s, E7s). - +%% maplist(+Predicate, ?Xs0, ?Xs1, ?Xs2, ?Xs3, ?Xs4, ?Xs5, ?Xs6, ?Xs7). +% +% This is a metapredicate that applies predicate to each element of the lists Xs0, Xs1, Xs2, Xs3, Xs4, Xs5, Xs6 and Xs7. maplist(_, [], [], [], [], [], [], [], []). maplist(Cont, [E1|E1s], [E2|E2s], [E3|E3s], [E4|E4s], [E5|E5s], [E6|E6s], [E7|E7s], [E8|E8s]) :- call(Cont, E1, E2, E3, E4, E5, E6, E7, E8), maplist(Cont, E1s, E2s, E3s, E4s, E5s, E6s, E7s, E8s). - +%% sum_list(+Xs, -Sum). +% +% Takes a lists of numbers and unifies Sum with the result of summing all the elements of the list. +% +% ?- sum_list([2,2,2], 6). +% true. sum_list(Ls, S) :- foldl(lists:sum_, Ls, 0, S). sum_(L, S0, S) :- S is S0 + L. - +%% same_length(?Xs, ?Ys). +% +% Succeeds if Xs and Ys are lists of the same length same_length([], []). same_length([_|As], [_|Bs]) :- same_length(As, Bs). +%% foldl(+Predicate, ?Ls, +A0, ?A). +% +% foldl, sometimes called reduce, is a metapredicate that takes a predicate, a list of items +% and a starting value, and outputs a single value. The predicate _Predicate_ must be able to take the current +% element of the list, the previous value of the computation and the next value of the computation. +% +% For example, if we define sum_ as: +% +% sum_(L, S0, S) :- S is S0 + L. +% +% Then we can define sum\_list/2 as the following: +% +% sum_list(Ls, S) :- foldl(sum_, Ls, 0, S). +% foldl(Goal_3, Ls, A0, A) :- foldl_(Ls, Goal_3, A0, A). @@ -191,7 +289,9 @@ foldl_([L|Ls], G_3, A0, A) :- call(G_3, L, A0, A1), foldl_(Ls, G_3, A1, A). - +%% foldl(+Predicate, ?Ls0, ?Ls1, +A0, ?A). +% +% Same as foldl/4 but with an extra list foldl(Goal_4, Xs, Ys, A0, A) :- foldl_(Xs, Ys, Goal_4, A0, A). @@ -201,6 +301,13 @@ foldl_([X|Xs], [Y|Ys], G_4, A0, A) :- call(G_4, X, Y, A0, A1), foldl_(Xs, Ys, G_4, A1, A). +%% transpose(?Ls, ?Ts). +% +% If Ls is a list of lists, Ts contains the transposition +% +% ?- transpose([[1,1],[2,2]], Ts). +% Ts = [[1,2],[1,2]]. +% transpose(Ls, Ts) :- lists_transpose(Ls, Ts). @@ -214,7 +321,13 @@ transpose_(_, Fs, Lists0, Lists) :- list_first_rest([L|Ls], L, Ls). - +%% list_to_set(+Ls0, -Set). +% +% Takes a list Ls0 and returns a list Set that doesn't contain any repeated element +% +% ?- list_to_set([2,3,4,4,1,2], Set). +% Set = [2,3,4,1]. +% list_to_set(Ls0, Ls) :- maplist(lists:with_var, Ls0, LVs0), keysort(LVs0, LVs), @@ -242,7 +355,12 @@ unify_same(E-V, Prev-Var, E-V) :- ; true ). - +%% nth0(?N, ?Ls, ?E). +% +% Succeeds if in the N position of the list Ls, we found the element E. The elements start counting from zero. +% +% ?- nth0(2, [1,2,3,4], 3). +% true. nth0(N, Es0, E) :- nonvar(N), '$skip_max_list'(Skip, N, Es0,Es1), @@ -277,6 +395,12 @@ nth0_el(N0,N, _,E, [E0|Es0]) :- N1 is N0+1, nth0_el(N1,N, E0,E, Es0). +%% nth1(?N, ?Ls, ?E). +% +% Succeeds if in the N position of the list Ls, we found the element E. The elements start counting from one. +% +% ?- nth1(2, [1,2,3,4], 2). +% true. nth1(N, Es0, E) :- N \== 0, nth0(N, [_|Es0], E), @@ -291,6 +415,12 @@ skipn(N0, Es0,Es, Xs0,Xs) :- skipn(N1, Es1,Es, Xs1,Xs). skipn(0, Es,Es, Xs,Xs). +%% nth0(?N, ?Ls, ?E, ?Rs). +% +% Succeeds if in the N position of the list Ls, we found the element E and the rest of the list is Rs. The elements start counting from zero. +% +% ?- nth0(2, [1,2,3,4], 3, [1,2,4]). +% true. nth0(N, Es0, E, Es) :- integer(N), N >= 0, @@ -315,45 +445,54 @@ nth0_elx(N0,N, E0,E, [E1|Es0], [E0|Es]) :- % p.p.8.5 +%% nth1(?N, ?Ls, ?E, ?Rs). +% +% Succeeds if in the N position of the list Ls, we found the element E and the rest of the list is Rs. The elements start counting from one. +% +% ?- nth1(2, [1,2,3,4], 2, [1,3,4]). +% true. nth1(N, Es0, E, Es) :- N \== 0, nth0(N, [_|Es0], E, [_|Es]), N \== 0. - +%% list_max(+Xs, -Max). +% +% Takes a list Xs and unifies with the maximum value of the list list_max([N|Ns], Max) :- foldl(lists:list_max_, Ns, N, Max). list_max_(N, Max0, Max) :- Max is max(N, Max0). +%% list_min(+Xs, -Min). +% +% Takes a list Xs and unifies with the minimum value of the list list_min([N|Ns], Min) :- foldl(lists:list_min_, Ns, N, Min). list_min_(N, Min0, Min) :- Min is min(N, Min0). -%! permutation(?Xs, ?Ys) is nondet. +%% permutation(?Xs, ?Ys) is nondet. % -% True when Xs is a permutation of Ys. This can solve for Ys given -% Xs or Xs given Ys, or even enumerate Xs and Ys together. The -% predicate permutation/2 is primarily intended to generate -% permutations. Note that a list of length N has N! permutations, -% and unbounded permutation generation becomes prohibitively -% expensive, even for rather short lists (10! = 3,628,800). +% True when Xs is a permutation of Ys. This can solve for Ys given +% Xs or Xs given Ys, or even enumerate Xs and Ys together. The +% predicate permutation/2 is primarily intended to generate +% permutations. Note that a list of length N has N! permutations, +% and unbounded permutation generation becomes prohibitively +% expensive, even for rather short lists (10! = 3,628,800). % -% The example below illustrates that Xs and Ys being proper lists -% is not a sufficient condition to use the above replacement. +% The example below illustrates that Xs and Ys being proper lists +% is not a sufficient condition to use the above replacement. % -% == % ?- permutation([1,2], [X,Y]). -% X = 1, Y = 2 ; -% X = 2, Y = 1 ; -% false. -% == +% X = 1, Y = 2 +% ; X = 2, Y = 1 +% ; false. % -% @error type_error(list, Arg) if either argument is not a proper -% or partial list. +% Throws type\_error(list, Arg) if either argument is not a proper +% or partial list. permutation(Xs, Ys) :- '$skip_max_list'(Xlen, _, Xs, XTail),