]> Repositorios git - scryer-prolog.git/commitdiff
ENHANCED: Much improved nth0/3, taken from #1529.
authorMarkus Triska <[email protected]>
Wed, 24 Aug 2022 19:11:54 +0000 (21:11 +0200)
committerMark Thom <[email protected]>
Thu, 27 Oct 2022 05:36:07 +0000 (23:36 -0600)
This also adds nth0/4 and bootstraps nth1/[3,4] from it.

src/lib/lists.pl

index 7cfffa17736eeeae0cf58b76303c0d080c2cb870..8103c28eba0a3a10bc0981b9f2d4ca6d0cfcbafc 100644 (file)
@@ -1,7 +1,7 @@
 :- 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,
-                         maplist/7, maplist/8, maplist/9, same_length/2, nth0/3,
+                         maplist/7, maplist/8, maplist/9, same_length/2, nth0/3, nth0/4, nth1/3, nth1/4,
                          sum_list/2, transpose/2, list_to_set/2, list_max/2,
                   list_min/2, permutation/2]).
 
@@ -243,21 +243,53 @@ unify_same(E-V, Prev-Var, E-V) :-
         ).
 
 
-nth0(N, Es, E) :-
-        can_be(integer, N),
-        can_be(list, Es),
-        (   integer(N) ->
-            '$skip_max_list'(N, N, Es, [E|_])
-        ;   nth0_search(N, Es, E)
-        ).
-
-nth0_search(N, Es, E) :-
-        nth0_search(0, N, Es, E).
-
-nth0_search(N, N, [E|_], E).
-nth0_search(N0, N, [_|Es], E) :-
-        N1 is N0 + 1,
-        nth0_search(N1, N, Es, E).
+nth0(N, Es0, E, Es) :-
+   nonvar(N),
+   '$skip_max_list'(Skip, N, Es0,Es1),
+   !,
+   (  Skip == N
+   -> Es1 = [E|Es]
+   ;  ( var(Es1) ; Es1 = [_|_] ) % a partial or infinite list
+   -> R is N-Skip,
+      skipn(R,Es1,Es2),
+      Es2 = [E|Es]
+   ).
+nth0(N, Es0, E, Es) :-
+   can_be(not_less_than_zero, N),
+   Es0 = [E0|Es1],
+   nth0_el(0,N, E0,E, Es1,Es).
+
+skipn(N0, Es0,Es) :-
+   N0>0,
+   !, % should not be necessary #1028
+   Es0 = [_|Es1],
+   N1 is N0-1,
+   skipn(N1, Es1,Es).
+skipn(0, Es,Es).
+
+nth0_el(N0,N, E0,E, Es0,Es) :-
+   Es0 == [],
+   !, % indexing
+   N0 = N,
+   E0 = E,
+   Es0 = Es.
+nth0_el(N,N, E,E, Es,Es).
+nth0_el(N0,N, _,E, [E0|Es0],Es) :-
+   N1 is N0+1,
+   nth0_el(N1,N, E0,E, Es0,Es).
+
+% p.p.8.5
+
+nth0(N, Es0, E) :-
+   nth0(N, Es0, E, _).
+
+nth1(N, Es0, E, Es) :-
+   N \== 0,
+   nth0(N, [_|Es0], E, Es),
+   N \== 0.
+
+nth1(N, Es0, E) :-
+   nth1(N, Es0, E, _).
 
 
 list_max([N|Ns], Max) :-