~ chicken-core (chicken-5) /mini-srfi-1.scm
Trap1;;;; minimal implementation of SRFI-1 primitives
2;
3;
4; Copyright (c) 2015-2022, The CHICKEN Team
5; All rights reserved.
6;
7; Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
8; conditions are met:
9;
10; Redistributions of source code must retain the above copyright notice, this list of conditions and the following
11; disclaimer.
12; Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
13; disclaimer in the documentation and/or other materials provided with the distribution.
14; Neither the name of the author nor the names of its contributors may be used to endorse or promote
15; products derived from this software without specific prior written permission.
16;
17; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
18; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
19; AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
20; CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22; SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25; POSSIBILITY OF SUCH DAMAGE.
26
27
28(declare
29 (unused take span drop partition split-at append-map every any cons* concatenate
30 first second third fourth alist-cons fifth remove
31 filter filter-map unzip1 last list-index lset-adjoin/eq? lset-difference/eq?
32 lset-union/eq? lset-intersection/eq? list-tabulate lset<=/eq? lset=/eq? length+
33 find find-tail iota make-list posq posv)
34 (hide take span drop partition split-at append-map every any cons* concatenate delete
35 first second third fourth alist-cons delete-duplicates fifth remove
36 filter filter-map unzip1 last list-index lset-adjoin/eq? lset-difference/eq?
37 lset-union/eq? lset-intersection/eq? list-tabulate lset<=/eq? lset=/eq? length+
38 find find-tail iota make-list posq posv))
39
40
41(define (partition pred lst)
42 (let loop ((yes '()) (no '()) (lst lst))
43 (cond ((null? lst) (values (reverse yes) (reverse no)))
44 ((pred (car lst)) (loop (cons (car lst) yes) no (cdr lst)))
45 (else (loop yes (cons (car lst) no) (cdr lst))))))
46
47(define (span pred lst)
48 (let loop ((lst lst) (head '()))
49 (cond ((null? lst) (values (reverse head) lst))
50 ((pred (car lst)) (loop (cdr lst) (cons (car lst) head)))
51 (else (values (reverse head) lst)))))
52
53(define (take lst n)
54 (if (fx<= n 0)
55 '()
56 (cons (car lst) (take (cdr lst) (fx- n 1)))))
57
58(define (drop lst n)
59 (let loop ((lst lst) (n n))
60 (if (fx<= n 0)
61 lst
62 (loop (cdr lst) (fx- n 1)))))
63
64(define (split-at lst n)
65 (let loop ((n n) (prev '()) (node lst))
66 (if (fx<= n 0)
67 (values (reverse prev) node)
68 (loop (fx- n 1) (cons (car node) prev) (cdr node)))))
69
70(define (append-map proc lst1 . lsts)
71 (if (null? lsts)
72 (foldr (lambda (x r) (append (proc x) r)) '() lst1)
73 (let loop ((lsts (cons lst1 lsts)))
74 (if (any null? lsts)
75 '()
76 (append (apply proc (map (lambda (x) (car x)) lsts))
77 (loop (map (lambda (x) (cdr x)) lsts)))))))
78
79(define (every pred lst)
80 (let loop ((lst lst))
81 (cond ((null? lst))
82 ((not (pred (car lst))) #f)
83 (else (loop (cdr lst))))))
84
85(define (any pred lst)
86 (let loop ((lst lst))
87 (cond ((null? lst) #f)
88 ((pred (car lst)))
89 (else (loop (cdr lst))))))
90
91(define (cons* x1 . xs)
92 (let loop ((x x1) (rest xs))
93 (if (null? rest)
94 x
95 (cons x (loop (car rest) (cdr rest))))))
96
97(define (concatenate lst)
98 (let loop ((lst lst))
99 (if (null? lst)
100 '()
101 (append (car lst) (loop (cdr lst))))))
102
103(define (delete x lst test)
104 (let loop ((lst lst))
105 (cond ((null? lst) lst)
106 ((test x (car lst))
107 (loop (cdr lst)))
108 (else
109 (cons (car lst) (loop (cdr lst)))))))
110
111(define (first x) (car x))
112(define (second x) (cadr x))
113(define (third x) (caddr x))
114(define (fourth x) (cadddr x))
115(define (fifth x) (car (cddddr x)))
116
117(define (delete-duplicates lst test)
118 (let loop ((lst lst))
119 (if (null? lst)
120 lst
121 (let* ((x (car lst))
122 (tail (cdr lst))
123 (new-tail (loop (delete x tail test))))
124 (if (equal? tail new-tail)
125 lst
126 (cons x new-tail))))))
127
128(define (alist-cons x y z) (cons (cons x y) z))
129
130(define (filter pred lst)
131 (foldr (lambda (x r) (if (pred x) (cons x r) r)) '() lst))
132
133(define (filter-map pred lst)
134 (foldr (lambda (x r)
135 (cond ((pred x) => (lambda (y) (cons y r)))
136 (else r)))
137 '()
138 lst))
139
140(define (remove pred lst)
141 (filter (lambda (x) (not (pred x))) lst))
142
143(define (unzip1 lst) (map (lambda (x) (car x)) lst))
144
145(define (last lst)
146 (let loop ((lst lst))
147 (if (null? (cdr lst))
148 (car lst)
149 (loop (cdr lst)))))
150
151(define (list-index pred lst)
152 (let loop ((i 0) (lst lst))
153 (cond ((null? lst) #f)
154 ((pred (car lst)) i)
155 (else (loop (fx+ i 1) (cdr lst))))))
156
157(define (lset-adjoin/eq? lst . vals)
158 (let loop ((vals vals) (lst lst))
159 (cond ((null? vals) lst)
160 ((memq (car vals) lst) (loop (cdr vals) lst))
161 (else (loop (cdr vals) (cons (car vals) lst))))))
162
163(define (lset-difference/eq? ls . lss)
164 (foldl
165 (lambda (ls lst)
166 (filter (lambda (x) (not (memq x lst))) ls))
167 ls
168 lss))
169
170(define (lset-union/eq? ls . lss)
171 (foldl
172 (lambda (ls lst)
173 (foldl
174 (lambda (ls x)
175 (if (any (lambda (y) (eq? y x)) ls)
176 ls
177 (cons x ls)))
178 ls lst))
179 ls lss))
180
181(define (lset-intersection/eq? ls1 . lss)
182 (filter (lambda (x)
183 (every (lambda (lis) (memq x lis)) lss))
184 ls1))
185
186(define (list-tabulate n proc)
187 (let loop ((i 0))
188 (if (fx>= i n)
189 '()
190 (cons (proc i) (loop (fx+ i 1))))))
191
192(define (lset<=/eq? s1 s2)
193 (every (lambda (s) (memq s s2)) s1))
194
195(define (lset=/eq? s1 s2)
196 (and (eq? (length s1) (length s2))
197 (every (lambda (s) (memq s s2)) s1)))
198
199;; from SRFI-1 ref. impl.
200(define (length+ x) ; Returns #f if X is circular.
201 (let lp ((x x) (lag x) (len 0))
202 (if (pair? x)
203 (let ((x (cdr x))
204 (len (fx+ len 1)))
205 (if (pair? x)
206 (let ((x (cdr x))
207 (lag (cdr lag))
208 (len (fx+ len 1)))
209 (and (not (eq? x lag)) (lp x lag len)))
210 len))
211 len)))
212
213(define (find pred lst)
214 (let loop ((lst lst))
215 (cond ((null? lst) #f)
216 ((pred (car lst)) (car lst))
217 (else (loop (cdr lst))))))
218
219(define (find-tail pred ls)
220 (let lp ((ls ls))
221 (cond ((null? ls) #f)
222 ((pred (car ls)) ls)
223 (else (lp (cdr ls))))))
224
225(define (iota n) (list-tabulate n (lambda (i) i)))
226
227(define (make-list n #!optional x)
228 (list-tabulate n (lambda _ x)))
229
230(define (posq x lst)
231 (let loop ((i 0) (lst lst))
232 (cond ((null? lst) #f)
233 ((eq? (car lst) x) i)
234 (else (loop (fx+ i 1) (cdr lst))))))
235
236(define (posv x lst)
237 (let loop ((i 0) (lst lst))
238 (cond ((null? lst) #f)
239 ((eqv? (car lst) x) i)
240 (else (loop (fx+ i 1) (cdr lst))))))
241