1;;; SRFI-1 list-processing library 			-*- Scheme -*-
2;;; Reference implementation
3;;;
4;;; Copyright (c) 1998, 1999 by Olin Shivers. You may do as you please with
5;;; this code as long as you do not remove this copyright notice or
6;;; hold me liable for its use. Please send bug reports to shivers@ai.mit.edu.
7;;;     -Olin
8
9;;; Copyright (c) 2007-2008 SigScheme Project <uim-en AT googlegroups.com>
10
11;; ChangeLog
12;;
13;; 2007-06-15 yamaken   - Imported from
14;;                        http://srfi.schemers.org/srfi-1/srfi-1-reference.scm
15;;                        and adapted to SigScheme
16;;                      - Add for-each
17;; 2007-06-30 yamaken   - Fix broken arguments receiving of delete-duplicates!
18;;                      - Fix broken lset-difference call of lset-xor and
19;;                        lset-xor! (as like as Scheme48)
20;; 2007-07-01 yamaken   - Fix broken comparison of list= on 3 or more lists
21;; 2007-07-13 yamaken   - Change default value for make-list to #<undef>
22
23
24;;; This is a library of list- and pair-processing functions. I wrote it after
25;;; carefully considering the functions provided by the libraries found in
26;;; R4RS/R5RS Scheme, MIT Scheme, Gambit, RScheme, MzScheme, slib, Common
27;;; Lisp, Bigloo, guile, T, APL and the SML standard basis. It is a pretty
28;;; rich toolkit, providing a superset of the functionality found in any of
29;;; the various Schemes I considered.
30
31;;; This implementation is intended as a portable reference implementation
32;;; for SRFI-1. See the porting notes below for more information.
33
34;;; Exported:
35;;; xcons tree-copy make-list list-tabulate cons* list-copy
36;;; proper-list? circular-list? dotted-list? not-pair? null-list? list=
37;;; circular-list length+
38;;; iota
39;;; first second third fourth fifth sixth seventh eighth ninth tenth
40;;; car+cdr
41;;; take       drop
42;;; take-right drop-right
43;;; take!      drop-right!
44;;; split-at   split-at!
45;;; last last-pair
46;;; zip unzip1 unzip2 unzip3 unzip4 unzip5
47;;; count
48;;; append! append-reverse append-reverse! concatenate concatenate!
49;;; unfold       fold       pair-fold       reduce
50;;; unfold-right fold-right pair-fold-right reduce-right
51;;; append-map append-map! map! pair-for-each filter-map map-in-order
52;;; filter  partition  remove
53;;; filter! partition! remove!
54;;; find find-tail any every list-index
55;;; take-while drop-while take-while!
56;;; span break span! break!
57;;; delete delete!
58;;; alist-cons alist-copy
59;;; delete-duplicates delete-duplicates!
60;;; alist-delete alist-delete!
61;;; reverse!
62;;; lset<= lset= lset-adjoin
63;;; lset-union  lset-intersection  lset-difference  lset-xor  lset-diff+intersection
64;;; lset-union! lset-intersection! lset-difference! lset-xor! lset-diff+intersection!
65;;;
66;;; In principle, the following R4RS list- and pair-processing procedures
67;;; are also part of this package's exports, although they are not defined
68;;; in this file:
69;;;   Primitives: cons pair? null? car cdr set-car! set-cdr!
70;;;   Non-primitives: list length append reverse cadr ... cddddr list-ref
71;;;                   memq memv assq assv
72;;;   (The non-primitives are defined in this file, but commented out.)
73;;;
74;;; These R4RS procedures have extended definitions in SRFI-1 and are defined
75;;; in this file:
76;;;   map for-each member assoc
77;;;
78;;; The remaining two R4RS list-processing procedures are not included:
79;;;   list-tail (use drop)
80;;;   list? (use proper-list?)
81
82
83;;; A note on recursion and iteration/reversal:
84;;; Many iterative list-processing algorithms naturally compute the elements
85;;; of the answer list in the wrong order (left-to-right or head-to-tail) from
86;;; the order needed to cons them into the proper answer (right-to-left, or
87;;; tail-then-head). One style or idiom of programming these algorithms, then,
88;;; loops, consing up the elements in reverse order, then destructively
89;;; reverses the list at the end of the loop. I do not do this. The natural
90;;; and efficient way to code these algorithms is recursively. This trades off
91;;; intermediate temporary list structure for intermediate temporary stack
92;;; structure. In a stack-based system, this improves cache locality and
93;;; lightens the load on the GC system. Don't stand on your head to iterate!
94;;; Recurse, where natural. Multiple-value returns make this even more
95;;; convenient, when the recursion/iteration has multiple state values.
96
97;;; Porting:
98;;; This is carefully tuned code; do not modify casually.
99;;;   - It is careful to share storage when possible;
100;;;   - Side-effecting code tries not to perform redundant writes.
101;;;
102;;; That said, a port of this library to a specific Scheme system might wish
103;;; to tune this code to exploit particulars of the implementation.
104;;; The single most important compiler-specific optimisation you could make
105;;; to this library would be to add rewrite rules or transforms to:
106;;; - transform applications of n-ary procedures (e.g. LIST=, CONS*, APPEND,
107;;;   LSET-UNION) into multiple applications of a primitive two-argument
108;;;   variant.
109;;; - transform applications of the mapping functions (MAP, FOR-EACH, FOLD,
110;;;   ANY, EVERY) into open-coded loops. The killer here is that these
111;;;   functions are n-ary. Handling the general case is quite inefficient,
112;;;   requiring many intermediate data structures to be allocated and
113;;;   discarded.
114;;; - transform applications of procedures that take optional arguments
115;;;   into calls to variants that do not take optional arguments. This
116;;;   eliminates unnecessary consing and parsing of the rest parameter.
117;;;
118;;; These transforms would provide BIG speedups. In particular, the n-ary
119;;; mapping functions are particularly slow and cons-intensive, and are good
120;;; candidates for tuning. I have coded fast paths for the single-list cases,
121;;; but what you really want to do is exploit the fact that the compiler
122;;; usually knows how many arguments are being passed to a particular
123;;; application of these functions -- they are usually explicitly called, not
124;;; passed around as higher-order values. If you can arrange to have your
125;;; compiler produce custom code or custom linkages based on the number of
126;;; arguments in the call, you can speed these functions up a *lot*. But this
127;;; kind of compiler technology no longer exists in the Scheme world as far as
128;;; I can see.
129;;;
130;;; Note that this code is, of course, dependent upon standard bindings for
131;;; the R5RS procedures -- i.e., it assumes that the variable CAR is bound
132;;; to the procedure that takes the car of a list. If your Scheme
133;;; implementation allows user code to alter the bindings of these procedures
134;;; in a manner that would be visible to these definitions, then there might
135;;; be trouble. You could consider horrible kludgery along the lines of
136;;;    (define fact
137;;;      (let ((= =) (- -) (* *))
138;;;        (letrec ((real-fact (lambda (n)
139;;;                              (if (= n 0) 1 (* n (real-fact (- n 1)))))))
140;;;          real-fact)))
141;;; Or you could consider shifting to a reasonable Scheme system that, say,
142;;; has a module system protecting code from this kind of lossage.
143;;;
144;;; This code does a fair amount of run-time argument checking. If your
145;;; Scheme system has a sophisticated compiler that can eliminate redundant
146;;; error checks, this is no problem. However, if not, these checks incur
147;;; some performance overhead -- and, in a safe Scheme implementation, they
148;;; are in some sense redundant: if we don't check to see that the PROC
149;;; parameter is a procedure, we'll find out anyway three lines later when
150;;; we try to call the value. It's pretty easy to rip all this argument
151;;; checking code out if it's inappropriate for your implementation -- just
152;;; nuke every call to CHECK-ARG.
153;;;
154;;; On the other hand, if you *do* have a sophisticated compiler that will
155;;; actually perform soft-typing and eliminate redundant checks (Rice's systems
156;;; being the only possible candidate of which I'm aware), leaving these checks
157;;; in can *help*, since their presence can be elided in redundant cases,
158;;; and in cases where they are needed, performing the checks early, at
159;;; procedure entry, can "lift" a check out of a loop.
160;;;
161;;; Finally, I have only checked the properties that can portably be checked
162;;; with R5RS Scheme -- and this is not complete. You may wish to alter
163;;; the CHECK-ARG parameter checks to perform extra, implementation-specific
164;;; checks, such as procedure arity for higher-order values.
165;;;
166;;; The code has only these non-R4RS dependencies:
167;;;   A few calls to an ERROR procedure;
168;;;   Uses of the R5RS multiple-value procedure VALUES and the m-v binding
169;;;     RECEIVE macro (which isn't R5RS, but is a trivial macro).
170;;;   Many calls to a parameter-checking procedure check-arg:
171;;;    (define (check-arg pred val caller)
172;;;      (let lp ((val val))
173;;;        (if (pred val) val (lp (error "Bad argument" val pred caller)))))
174;;;   A few uses of the LET-OPTIONAL and :OPTIONAL macros for parsing
175;;;     optional arguments.
176;;;
177;;; Most of these procedures use the NULL-LIST? test to trigger the
178;;; base case in the inner loop or recursion. The NULL-LIST? function
179;;; is defined to be a careful one -- it raises an error if passed a
180;;; non-nil, non-pair value. The spec allows an implementation to use
181;;; a less-careful implementation that simply defines NULL-LIST? to
182;;; be NOT-PAIR?. This would speed up the inner loops of these procedures
183;;; at the expense of having them silently accept dotted lists.
184
185;;; A note on dotted lists:
186;;; I, personally, take the view that the only consistent view of lists
187;;; in Scheme is the view that *everything* is a list -- values such as
188;;; 3 or "foo" or 'bar are simply empty dotted lists. This is due to the
189;;; fact that Scheme actually has no true list type. It has a pair type,
190;;; and there is an *interpretation* of the trees built using this type
191;;; as lists.
192;;;
193;;; I lobbied to have these list-processing procedures hew to this
194;;; view, and accept any value as a list argument. I was overwhelmingly
195;;; overruled during the SRFI discussion phase. So I am inserting this
196;;; text in the reference lib and the SRFI spec as a sort of "minority
197;;; opinion" dissent.
198;;;
199;;; Many of the procedures in this library can be trivially redefined
200;;; to handle dotted lists, just by changing the NULL-LIST? base-case
201;;; check to NOT-PAIR?, meaning that any non-pair value is taken to be
202;;; an empty list. For most of these procedures, that's all that is
203;;; required.
204;;;
205;;; However, we have to do a little more work for some procedures that
206;;; *produce* lists from other lists.  Were we to extend these procedures to
207;;; accept dotted lists, we would have to define how they terminate the lists
208;;; produced as results when passed a dotted list. I designed a coherent set
209;;; of termination rules for these cases; this was posted to the SRFI-1
210;;; discussion list. I additionally wrote an earlier version of this library
211;;; that implemented that spec. It has been discarded during later phases of
212;;; the definition and implementation of this library.
213;;;
214;;; The argument *against* defining these procedures to work on dotted
215;;; lists is that dotted lists are the rare, odd case, and that by
216;;; arranging for the procedures to handle them, we lose error checking
217;;; in the cases where a dotted list is passed by accident -- e.g., when
218;;; the programmer swaps a two arguments to a list-processing function,
219;;; one being a scalar and one being a list. For example,
220;;;     (member '(1 3 5 7 9) 7)
221;;; This would quietly return #f if we extended MEMBER to accept dotted
222;;; lists.
223;;;
224;;; The SRFI discussion record contains more discussion on this topic.
225
226;;; SigScheme adaptation
227;;;;;;;;;;;;;;;;;;;;;;;;
228
229(require-extension (srfi 8 23))
230
231(define %srfi-1:undefined (for-each values '()))
232
233(define (check-arg pred val caller)
234  (let lp ((val val))
235    (if (pred val) val (lp (error "Bad argument" val pred caller)))))
236;; If you need efficiency, define this once SRFI-1 has been enabled.
237;;(define (check-arg . args) #f)
238
239(define :optional
240  (lambda (opt default)
241    (case (length opt)
242     ((0)  default)
243     ((1)  (car opt))
244     (else (error "superfluous arguments")))))
245
246
247;;; Constructors
248;;;;;;;;;;;;;;;;
249
250;;; Occasionally useful as a value to be passed to a fold or other
251;;; higher-order procedure.
252(define (xcons d a) (cons a d))
253
254;;;; Recursively copy every cons.
255;(define (tree-copy x)
256;  (let recur ((x x))
257;    (if (not (pair? x)) x
258;	(cons (recur (car x)) (recur (cdr x))))))
259
260;;; Make a list of length LEN.
261
262(define (make-list len . maybe-elt)
263  (check-arg (lambda (n) (and (integer? n) (>= n 0))) len make-list)
264  (let ((elt (cond ((null? maybe-elt) %srfi-1:undefined) ; Default value
265		   ((null? (cdr maybe-elt)) (car maybe-elt))
266		   (else (error "Too many arguments to MAKE-LIST"
267				(cons len maybe-elt))))))
268    (do ((i len (- i 1))
269	 (ans '() (cons elt ans)))
270	((<= i 0) ans))))
271
272
273;(define (list . ans) ans)	; R4RS
274
275
276;;; Make a list of length LEN. Elt i is (PROC i) for 0 <= i < LEN.
277
278(define (list-tabulate len proc)
279  (check-arg (lambda (n) (and (integer? n) (>= n 0))) len list-tabulate)
280  (check-arg procedure? proc list-tabulate)
281  (do ((i (- len 1) (- i 1))
282       (ans '() (cons (proc i) ans)))
283      ((< i 0) ans)))
284
285;;; (cons* a1 a2 ... an) = (cons a1 (cons a2 (cons ... an)))
286;;; (cons* a1) = a1	(cons* a1 a2 ...) = (cons a1 (cons* a2 ...))
287;;;
288;;; (cons first (unfold not-pair? car cdr rest values))
289
290(define (cons* first . rest)
291  (let recur ((x first) (rest rest))
292    (if (pair? rest)
293	(cons x (recur (car rest) (cdr rest)))
294	x)))
295
296;;; (unfold not-pair? car cdr lis values)
297
298(define (list-copy lis)
299  (let recur ((lis lis))
300    (if (pair? lis)
301	(cons (car lis) (recur (cdr lis)))
302	lis)))
303
304;;; IOTA count [start step]	(start start+step ... start+(count-1)*step)
305
306(define (iota count . maybe-start+step)
307  (check-arg integer? count iota)
308  (if (< count 0) (error "Negative step count" iota count))
309  (let-optionals* maybe-start+step ((start 0) (step 1) . must-be-null)
310    (check-arg number? start iota)
311    (check-arg number? step iota)
312    (if (not (null? must-be-null)) (error "superfluous arguments"))
313    (let ((last-val (+ start (* (- count 1) step))))
314      (do ((count count (- count 1))
315	   (val last-val (- val step))
316	   (ans '() (cons val ans)))
317	  ((<= count 0)  ans)))))
318
319;;; I thought these were lovely, but the public at large did not share my
320;;; enthusiasm...
321;;; :IOTA to		(0 ... to-1)
322;;; :IOTA from to	(from ... to-1)
323;;; :IOTA from to step  (from from+step ...)
324
325;;; IOTA: to		(1 ... to)
326;;; IOTA: from to	(from+1 ... to)
327;;; IOTA: from to step	(from+step from+2step ...)
328
329;(define (%parse-iota-args arg1 rest-args proc)
330;  (let ((check (lambda (n) (check-arg integer? n proc))))
331;    (check arg1)
332;    (if (pair? rest-args)
333;	(let ((arg2 (check (car rest-args)))
334;	      (rest (cdr rest-args)))
335;	  (if (pair? rest)
336;	      (let ((arg3 (check (car rest)))
337;		    (rest (cdr rest)))
338;		(if (pair? rest) (error "Too many parameters" proc arg1 rest-args)
339;		    (values arg1 arg2 arg3)))
340;	      (values arg1 arg2 1)))
341;	(values 0 arg1 1))))
342;
343;(define (iota: arg1 . rest-args)
344;  (receive (from to step) (%parse-iota-args arg1 rest-args iota:)
345;    (let* ((numsteps (floor (/ (- to from) step)))
346;	   (last-val (+ from (* step numsteps))))
347;      (if (< numsteps 0) (error "Negative step count" iota: from to step))
348;      (do ((steps-left numsteps (- steps-left 1))
349;	   (val last-val (- val step))
350;	   (ans '() (cons val ans)))
351;	  ((<= steps-left 0) ans)))))
352;
353;
354;(define (:iota arg1 . rest-args)
355;  (receive (from to step) (%parse-iota-args arg1 rest-args :iota)
356;    (let* ((numsteps (ceiling (/ (- to from) step)))
357;	   (last-val (+ from (* step (- numsteps 1)))))
358;      (if (< numsteps 0) (error "Negative step count" :iota from to step))
359;      (do ((steps-left numsteps (- steps-left 1))
360;	   (val last-val (- val step))
361;	   (ans '() (cons val ans)))
362;	  ((<= steps-left 0) ans)))))
363
364
365
366(define (circular-list val1 . vals)
367  (let ((ans (cons val1 vals)))
368    (set-cdr! (last-pair ans) ans)
369    ans))
370
371;;; <proper-list> ::= ()			; Empty proper list
372;;;		  |   (cons <x> <proper-list>)	; Proper-list pair
373;;; Note that this definition rules out circular lists -- and this
374;;; function is required to detect this case and return false.
375
376(define (proper-list? x)
377  (let lp ((x x) (lag x))
378    (if (pair? x)
379	(let ((x (cdr x)))
380	  (if (pair? x)
381	      (let ((x   (cdr x))
382		    (lag (cdr lag)))
383		(and (not (eq? x lag)) (lp x lag)))
384	      (null? x)))
385	(null? x))))
386
387
388;;; A dotted list is a finite list (possibly of length 0) terminated
389;;; by a non-nil value. Any non-cons, non-nil value (e.g., "foo" or 5)
390;;; is a dotted list of length 0.
391;;;
392;;; <dotted-list> ::= <non-nil,non-pair>	; Empty dotted list
393;;;               |   (cons <x> <dotted-list>)	; Proper-list pair
394
395(define (dotted-list? x)
396  (let lp ((x x) (lag x))
397    (if (pair? x)
398	(let ((x (cdr x)))
399	  (if (pair? x)
400	      (let ((x   (cdr x))
401		    (lag (cdr lag)))
402		(and (not (eq? x lag)) (lp x lag)))
403	      (not (null? x))))
404	(not (null? x)))))
405
406(define (circular-list? x)
407  (let lp ((x x) (lag x))
408    (and (pair? x)
409	 (let ((x (cdr x)))
410	   (and (pair? x)
411		(let ((x   (cdr x))
412		      (lag (cdr lag)))
413		  (or (eq? x lag) (lp x lag))))))))
414
415(define (not-pair? x) (not (pair? x)))	; Inline me.
416
417;;; This is a legal definition which is fast and sloppy:
418;;;     (define null-list? not-pair?)
419;;; but we'll provide a more careful one:
420(define (null-list? l)
421  (cond ((pair? l) #f)
422	((null? l) #t)
423	(else (error "null-list?: argument out of domain" l))))
424
425
426(define (list= = . lists)
427  (or (null? lists) ; special case
428
429      (let lp1 ((list-a (car lists)) (others (cdr lists)))
430	(or (null? others)
431	    (let ((list-b (car others))
432		  (others (cdr others)))
433	      (if (eq? list-a list-b)	; EQ? => LIST=
434		  (lp1 list-b others)
435		  (let lp2 ((tail-a list-a) (tail-b list-b))
436		    (if (null-list? tail-a)
437			(and (null-list? tail-b)
438			     (lp1 list-b others))
439			(and (not (null-list? tail-b))
440			     (= (car tail-a) (car tail-b))
441			     (lp2 (cdr tail-a) (cdr tail-b)))))))))))
442
443
444
445;;; R4RS, so commented out.
446;(define (length x)			; LENGTH may diverge or
447;  (let lp ((x x) (len 0))		; raise an error if X is
448;    (if (pair? x)			; a circular list. This version
449;        (lp (cdr x) (+ len 1))		; diverges.
450;        len)))
451
452(define (length+ x)			; Returns #f if X is circular.
453  (let lp ((x x) (lag x) (len 0))
454    (if (pair? x)
455	(let ((x (cdr x))
456	      (len (+ len 1)))
457	  (if (pair? x)
458	      (let ((x   (cdr x))
459		    (lag (cdr lag))
460		    (len (+ len 1)))
461		(and (not (eq? x lag)) (lp x lag len)))
462	      len))
463	len)))
464
465(define (zip list1 . more-lists) (apply map list list1 more-lists))
466
467
468;;; Selectors
469;;;;;;;;;;;;;
470
471;;; R4RS non-primitives:
472;(define (caar   x) (car (car x)))
473;(define (cadr   x) (car (cdr x)))
474;(define (cdar   x) (cdr (car x)))
475;(define (cddr   x) (cdr (cdr x)))
476;
477;(define (caaar  x) (caar (car x)))
478;(define (caadr  x) (caar (cdr x)))
479;(define (cadar  x) (cadr (car x)))
480;(define (caddr  x) (cadr (cdr x)))
481;(define (cdaar  x) (cdar (car x)))
482;(define (cdadr  x) (cdar (cdr x)))
483;(define (cddar  x) (cddr (car x)))
484;(define (cdddr  x) (cddr (cdr x)))
485;
486;(define (caaaar x) (caaar (car x)))
487;(define (caaadr x) (caaar (cdr x)))
488;(define (caadar x) (caadr (car x)))
489;(define (caaddr x) (caadr (cdr x)))
490;(define (cadaar x) (cadar (car x)))
491;(define (cadadr x) (cadar (cdr x)))
492;(define (caddar x) (caddr (car x)))
493;(define (cadddr x) (caddr (cdr x)))
494;(define (cdaaar x) (cdaar (car x)))
495;(define (cdaadr x) (cdaar (cdr x)))
496;(define (cdadar x) (cdadr (car x)))
497;(define (cdaddr x) (cdadr (cdr x)))
498;(define (cddaar x) (cddar (car x)))
499;(define (cddadr x) (cddar (cdr x)))
500;(define (cdddar x) (cdddr (car x)))
501;(define (cddddr x) (cdddr (cdr x)))
502
503
504(define first  car)
505(define second cadr)
506(define third  caddr)
507(define fourth cadddr)
508(define (fifth   x) (car    (cddddr x)))
509(define (sixth   x) (cadr   (cddddr x)))
510(define (seventh x) (caddr  (cddddr x)))
511(define (eighth  x) (cadddr (cddddr x)))
512(define (ninth   x) (car  (cddddr (cddddr x))))
513(define (tenth   x) (cadr (cddddr (cddddr x))))
514
515(define (car+cdr pair) (values (car pair) (cdr pair)))
516
517;;; take & drop
518
519(define (take lis k)
520  (check-arg integer? k take)
521  (let recur ((lis lis) (k k))
522    (if (zero? k) '()
523	(cons (car lis)
524	      (recur (cdr lis) (- k 1))))))
525
526(define (drop lis k)
527  (check-arg integer? k drop)
528  (let iter ((lis lis) (k k))
529    (if (zero? k) lis (iter (cdr lis) (- k 1)))))
530
531(define (take! lis k)
532  (check-arg integer? k take!)
533  (if (zero? k) '()
534      (begin (set-cdr! (drop lis (- k 1)) '())
535	     lis)))
536
537;;; TAKE-RIGHT and DROP-RIGHT work by getting two pointers into the list,
538;;; off by K, then chasing down the list until the lead pointer falls off
539;;; the end.
540
541(define (take-right lis k)
542  (check-arg integer? k take-right)
543  (let lp ((lag lis)  (lead (drop lis k)))
544    (if (pair? lead)
545	(lp (cdr lag) (cdr lead))
546	lag)))
547
548(define (drop-right lis k)
549  (check-arg integer? k drop-right)
550  (let recur ((lag lis) (lead (drop lis k)))
551    (if (pair? lead)
552	(cons (car lag) (recur (cdr lag) (cdr lead)))
553	'())))
554
555;;; In this function, LEAD is actually K+1 ahead of LAG. This lets
556;;; us stop LAG one step early, in time to smash its cdr to ().
557(define (drop-right! lis k)
558  (check-arg integer? k drop-right!)
559  (let ((lead (drop lis k)))
560    (if (pair? lead)
561
562	(let lp ((lag lis)  (lead (cdr lead)))	; Standard case
563	  (if (pair? lead)
564	      (lp (cdr lag) (cdr lead))
565	      (begin (set-cdr! lag '())
566		     lis)))
567
568	'())))	; Special case dropping everything -- no cons to side-effect.
569
570;(define (list-ref lis i) (car (drop lis i)))	; R4RS
571
572;;; These use the APL convention, whereby negative indices mean
573;;; "from the right." I liked them, but they didn't win over the
574;;; SRFI reviewers.
575;;; K >= 0: Take and drop  K elts from the front of the list.
576;;; K <= 0: Take and drop -K elts from the end   of the list.
577
578;(define (take lis k)
579;  (check-arg integer? k take)
580;  (if (negative? k)
581;      (list-tail lis (+ k (length lis)))
582;      (let recur ((lis lis) (k k))
583;	(if (zero? k) '()
584;	    (cons (car lis)
585;		  (recur (cdr lis) (- k 1)))))))
586;
587;(define (drop lis k)
588;  (check-arg integer? k drop)
589;  (if (negative? k)
590;      (let recur ((lis lis) (nelts (+ k (length lis))))
591;	(if (zero? nelts) '()
592;	    (cons (car lis)
593;		  (recur (cdr lis) (- nelts 1)))))
594;      (list-tail lis k)))
595;
596;
597;(define (take! lis k)
598;  (check-arg integer? k take!)
599;  (cond ((zero? k) '())
600;	((positive? k)
601;	 (set-cdr! (list-tail lis (- k 1)) '())
602;	 lis)
603;	(else (list-tail lis (+ k (length lis))))))
604;
605;(define (drop! lis k)
606;  (check-arg integer? k drop!)
607;  (if (negative? k)
608;      (let ((nelts (+ k (length lis))))
609;	(if (zero? nelts) '()
610;	    (begin (set-cdr! (list-tail lis (- nelts 1)) '())
611;		   lis)))
612;      (list-tail lis k)))
613
614(define (split-at x k)
615  (check-arg integer? k split-at)
616  (let recur ((lis x) (k k))
617    (if (zero? k) (values '() lis)
618	(receive (prefix suffix) (recur (cdr lis) (- k 1))
619	  (values (cons (car lis) prefix) suffix)))))
620
621(define (split-at! x k)
622  (check-arg integer? k split-at!)
623  (if (zero? k) (values '() x)
624      (let* ((prev (drop x (- k 1)))
625	     (suffix (cdr prev)))
626	(set-cdr! prev '())
627	(values x suffix))))
628
629
630(define (last lis) (car (last-pair lis)))
631
632(define (last-pair lis)
633  (check-arg pair? lis last-pair)
634  (let lp ((lis lis))
635    (let ((tail (cdr lis)))
636      (if (pair? tail) (lp tail) lis))))
637
638
639;;; Unzippers -- 1 through 5
640;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
641
642(define (unzip1 lis) (map car lis))
643
644(define (unzip2 lis)
645  (let recur ((lis lis))
646    (if (null-list? lis) (values lis lis)	; Use NOT-PAIR? to handle
647	(let ((elt (car lis)))			; dotted lists.
648	  (receive (a b) (recur (cdr lis))
649	    (values (cons (car  elt) a)
650		    (cons (cadr elt) b)))))))
651
652(define (unzip3 lis)
653  (let recur ((lis lis))
654    (if (null-list? lis) (values lis lis lis)
655	(let ((elt (car lis)))
656	  (receive (a b c) (recur (cdr lis))
657	    (values (cons (car   elt) a)
658		    (cons (cadr  elt) b)
659		    (cons (caddr elt) c)))))))
660
661(define (unzip4 lis)
662  (let recur ((lis lis))
663    (if (null-list? lis) (values lis lis lis lis)
664	(let ((elt (car lis)))
665	  (receive (a b c d) (recur (cdr lis))
666	    (values (cons (car    elt) a)
667		    (cons (cadr   elt) b)
668		    (cons (caddr  elt) c)
669		    (cons (cadddr elt) d)))))))
670
671(define (unzip5 lis)
672  (let recur ((lis lis))
673    (if (null-list? lis) (values lis lis lis lis lis)
674	(let ((elt (car lis)))
675	  (receive (a b c d e) (recur (cdr lis))
676	    (values (cons (car     elt) a)
677		    (cons (cadr    elt) b)
678		    (cons (caddr   elt) c)
679		    (cons (cadddr  elt) d)
680		    (cons (car (cddddr  elt)) e)))))))
681
682
683;;; append! append-reverse append-reverse! concatenate concatenate!
684;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
685
686(define (append! . lists)
687  ;; First, scan through lists looking for a non-empty one.
688  (let lp ((lists lists) (prev '()))
689    (if (not (pair? lists)) prev
690	(let ((first (car lists))
691	      (rest (cdr lists)))
692	  (if (not (pair? first)) (lp rest first)
693
694	      ;; Now, do the splicing.
695	      (let lp2 ((tail-cons (last-pair first))
696			(rest rest))
697		(if (pair? rest)
698		    (let ((next (car rest))
699			  (rest (cdr rest)))
700		      (set-cdr! tail-cons next)
701		      (lp2 (if (pair? next) (last-pair next) tail-cons)
702			   rest))
703		    first)))))))
704
705;;; APPEND is R4RS.
706;(define (append . lists)
707;  (if (pair? lists)
708;      (let recur ((list1 (car lists)) (lists (cdr lists)))
709;        (if (pair? lists)
710;            (let ((tail (recur (car lists) (cdr lists))))
711;              (fold-right cons tail list1)) ; Append LIST1 & TAIL.
712;            list1))
713;      '()))
714
715;(define (append-reverse rev-head tail) (fold cons tail rev-head))
716
717;(define (append-reverse! rev-head tail)
718;  (pair-fold (lambda (pair tail) (set-cdr! pair tail) pair)
719;             tail
720;             rev-head))
721
722;;; Hand-inline the FOLD and PAIR-FOLD ops for speed.
723
724(define (append-reverse rev-head tail)
725  (let lp ((rev-head rev-head) (tail tail))
726    (if (null-list? rev-head) tail
727	(lp (cdr rev-head) (cons (car rev-head) tail)))))
728
729(define (append-reverse! rev-head tail)
730  (let lp ((rev-head rev-head) (tail tail))
731    (if (null-list? rev-head) tail
732	(let ((next-rev (cdr rev-head)))
733	  (set-cdr! rev-head tail)
734	  (lp next-rev rev-head)))))
735
736
737(define (concatenate  lists) (reduce-right append  '() lists))
738(define (concatenate! lists) (reduce-right append! '() lists))
739
740;;; Fold/map internal utilities
741;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
742;;; These little internal utilities are used by the general
743;;; fold & mapper funs for the n-ary cases . It'd be nice if they got inlined.
744;;; One the other hand, the n-ary cases are painfully inefficient as it is.
745;;; An aggressive implementation should simply re-write these functions
746;;; for raw efficiency; I have written them for as much clarity, portability,
747;;; and simplicity as can be achieved.
748;;;
749;;; I use the dreaded call/cc to do local aborts. A good compiler could
750;;; handle this with extreme efficiency. An implementation that provides
751;;; a one-shot, non-persistent continuation grabber could help the compiler
752;;; out by using that in place of the call/cc's in these routines.
753;;;
754;;; These functions have funky definitions that are precisely tuned to
755;;; the needs of the fold/map procs -- for example, to minimize the number
756;;; of times the argument lists need to be examined.
757
758;;; Return (map cdr lists).
759;;; However, if any element of LISTS is empty, just abort and return '().
760(define (%cdrs lists)
761  (call-with-current-continuation
762    (lambda (abort)
763      (let recur ((lists lists))
764	(if (pair? lists)
765	    (let ((lis (car lists)))
766	      (if (null-list? lis) (abort '())
767		  (cons (cdr lis) (recur (cdr lists)))))
768	    '())))))
769
770(define (%cars+ lists last-elt)	; (append! (map car lists) (list last-elt))
771  (let recur ((lists lists))
772    (if (pair? lists) (cons (caar lists) (recur (cdr lists))) (list last-elt))))
773
774;;; LISTS is a (not very long) non-empty list of lists.
775;;; Return two lists: the cars & the cdrs of the lists.
776;;; However, if any of the lists is empty, just abort and return [() ()].
777
778(define (%cars+cdrs lists)
779  (call-with-current-continuation
780    (lambda (abort)
781      (let recur ((lists lists))
782        (if (pair? lists)
783	    (receive (list other-lists) (car+cdr lists)
784	      (if (null-list? list) (abort '() '()) ; LIST is empty -- bail out
785		  (receive (a d) (car+cdr list)
786		    (receive (cars cdrs) (recur other-lists)
787		      (values (cons a cars) (cons d cdrs))))))
788	    (values '() '()))))))
789
790;;; Like %CARS+CDRS, but we pass in a final elt tacked onto the end of the
791;;; cars list. What a hack.
792(define (%cars+cdrs+ lists cars-final)
793  (call-with-current-continuation
794    (lambda (abort)
795      (let recur ((lists lists))
796        (if (pair? lists)
797	    (receive (list other-lists) (car+cdr lists)
798	      (if (null-list? list) (abort '() '()) ; LIST is empty -- bail out
799		  (receive (a d) (car+cdr list)
800		    (receive (cars cdrs) (recur other-lists)
801		      (values (cons a cars) (cons d cdrs))))))
802	    (values (list cars-final) '()))))))
803
804;;; Like %CARS+CDRS, but blow up if any list is empty.
805(define (%cars+cdrs/no-test lists)
806  (let recur ((lists lists))
807    (if (pair? lists)
808	(receive (list other-lists) (car+cdr lists)
809	  (receive (a d) (car+cdr list)
810	    (receive (cars cdrs) (recur other-lists)
811	      (values (cons a cars) (cons d cdrs)))))
812	(values '() '()))))
813
814
815;;; count
816;;;;;;;;;
817(define (count pred list1 . lists)
818  (check-arg procedure? pred count)
819  (if (pair? lists)
820
821      ;; N-ary case
822      (let lp ((list1 list1) (lists lists) (i 0))
823	(if (null-list? list1) i
824	    (receive (as ds) (%cars+cdrs lists)
825	      (if (null? as) i
826		  (lp (cdr list1) ds
827		      (if (apply pred (car list1) as) (+ i 1) i))))))
828
829      ;; Fast path
830      (let lp ((lis list1) (i 0))
831	(if (null-list? lis) i
832	    (lp (cdr lis) (if (pred (car lis)) (+ i 1) i))))))
833
834
835;;; fold/unfold
836;;;;;;;;;;;;;;;
837
838(define (unfold-right p f g seed . maybe-tail)
839  (check-arg procedure? p unfold-right)
840  (check-arg procedure? f unfold-right)
841  (check-arg procedure? g unfold-right)
842  (let lp ((seed seed) (ans (:optional maybe-tail '())))
843    (if (p seed) ans
844	(lp (g seed)
845	    (cons (f seed) ans)))))
846
847
848(define (unfold p f g seed . maybe-tail-gen)
849  (check-arg procedure? p unfold)
850  (check-arg procedure? f unfold)
851  (check-arg procedure? g unfold)
852  (if (pair? maybe-tail-gen)
853
854      (let ((tail-gen (car maybe-tail-gen)))
855	(if (pair? (cdr maybe-tail-gen))
856	    (apply error "Too many arguments" unfold p f g seed maybe-tail-gen)
857
858	    (let recur ((seed seed))
859	      (if (p seed) (tail-gen seed)
860		  (cons (f seed) (recur (g seed)))))))
861
862      (let recur ((seed seed))
863	(if (p seed) '()
864	    (cons (f seed) (recur (g seed)))))))
865
866
867(define (fold kons knil lis1 . lists)
868  (check-arg procedure? kons fold)
869  (if (pair? lists)
870      (let lp ((lists (cons lis1 lists)) (ans knil))	; N-ary case
871	(receive (cars+ans cdrs) (%cars+cdrs+ lists ans)
872	  (if (null? cars+ans) ans ; Done.
873	      (lp cdrs (apply kons cars+ans)))))
874
875      (let lp ((lis lis1) (ans knil))			; Fast path
876	(if (null-list? lis) ans
877	    (lp (cdr lis) (kons (car lis) ans))))))
878
879
880(define (fold-right kons knil lis1 . lists)
881  (check-arg procedure? kons fold-right)
882  (if (pair? lists)
883      (let recur ((lists (cons lis1 lists)))		; N-ary case
884	(let ((cdrs (%cdrs lists)))
885	  (if (null? cdrs) knil
886	      (apply kons (%cars+ lists (recur cdrs))))))
887
888      (let recur ((lis lis1))				; Fast path
889	(if (null-list? lis) knil
890	    (let ((head (car lis)))
891	      (kons head (recur (cdr lis))))))))
892
893
894(define (pair-fold-right f zero lis1 . lists)
895  (check-arg procedure? f pair-fold-right)
896  (if (pair? lists)
897      (let recur ((lists (cons lis1 lists)))		; N-ary case
898	(let ((cdrs (%cdrs lists)))
899	  (if (null? cdrs) zero
900	      (apply f (append! lists (list (recur cdrs)))))))
901
902      (let recur ((lis lis1))				; Fast path
903	(if (null-list? lis) zero (f lis (recur (cdr lis)))))))
904
905(define (pair-fold f zero lis1 . lists)
906  (check-arg procedure? f pair-fold)
907  (if (pair? lists)
908      (let lp ((lists (cons lis1 lists)) (ans zero))	; N-ary case
909	(let ((tails (%cdrs lists)))
910	  (if (null? tails) ans
911	      (lp tails (apply f (append! lists (list ans)))))))
912
913      (let lp ((lis lis1) (ans zero))
914	(if (null-list? lis) ans
915	    (let ((tail (cdr lis)))		; Grab the cdr now,
916	      (lp tail (f lis ans)))))))	; in case F SET-CDR!s LIS.
917
918
919;;; REDUCE and REDUCE-RIGHT only use RIDENTITY in the empty-list case.
920;;; These cannot meaningfully be n-ary.
921
922(define (reduce f ridentity lis)
923  (check-arg procedure? f reduce)
924  (if (null-list? lis) ridentity
925      (fold f (car lis) (cdr lis))))
926
927(define (reduce-right f ridentity lis)
928  (check-arg procedure? f reduce-right)
929  (if (null-list? lis) ridentity
930      (let recur ((head (car lis)) (lis (cdr lis)))
931	(if (pair? lis)
932	    (f head (recur (car lis) (cdr lis)))
933	    head))))
934
935
936
937;;; Mappers: append-map append-map! pair-for-each map! filter-map map-in-order
938;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
939
940(define (append-map f lis1 . lists)
941  (really-append-map append-map  append  f lis1 lists))
942(define (append-map! f lis1 . lists)
943  (really-append-map append-map! append! f lis1 lists))
944
945(define (really-append-map who appender f lis1 lists)
946  (check-arg procedure? f who)
947  (if (pair? lists)
948      (receive (cars cdrs) (%cars+cdrs (cons lis1 lists))
949	(if (null? cars) '()
950	    (let recur ((cars cars) (cdrs cdrs))
951	      (let ((vals (apply f cars)))
952		(receive (cars2 cdrs2) (%cars+cdrs cdrs)
953		  (if (null? cars2) vals
954		      (appender vals (recur cars2 cdrs2))))))))
955
956      ;; Fast path
957      (if (null-list? lis1) '()
958	  (let recur ((elt (car lis1)) (rest (cdr lis1)))
959	    (let ((vals (f elt)))
960	      (if (null-list? rest) vals
961		  (appender vals (recur (car rest) (cdr rest)))))))))
962
963
964(define (pair-for-each proc lis1 . lists)
965  (check-arg procedure? proc pair-for-each)
966  (if (pair? lists)
967
968      (let lp ((lists (cons lis1 lists)))
969	(let ((tails (%cdrs lists)))
970	  (if (pair? tails)
971	      (begin (apply proc lists)
972		     (lp tails)))))
973
974      ;; Fast path.
975      (let lp ((lis lis1))
976	(if (not (null-list? lis))
977	    (let ((tail (cdr lis)))	; Grab the cdr now,
978	      (proc lis)		; in case PROC SET-CDR!s LIS.
979	      (lp tail))))))
980
981;;; We stop when LIS1 runs out, not when any list runs out.
982(define (map! f lis1 . lists)
983  (check-arg procedure? f map!)
984  (if (pair? lists)
985      (let lp ((lis1 lis1) (lists lists))
986	(if (not (null-list? lis1))
987	    (receive (heads tails) (%cars+cdrs/no-test lists)
988	      (set-car! lis1 (apply f (car lis1) heads))
989	      (lp (cdr lis1) tails))))
990
991      ;; Fast path.
992      (pair-for-each (lambda (pair) (set-car! pair (f (car pair)))) lis1))
993  lis1)
994
995
996;;; Map F across L, and save up all the non-false results.
997(define (filter-map f lis1 . lists)
998  (check-arg procedure? f filter-map)
999  (if (pair? lists)
1000      (let recur ((lists (cons lis1 lists)))
1001	(receive (cars cdrs) (%cars+cdrs lists)
1002	  (if (pair? cars)
1003	      (cond ((apply f cars) => (lambda (x) (cons x (recur cdrs))))
1004		    (else (recur cdrs))) ; Tail call in this arm.
1005	      '())))
1006
1007      ;; Fast path.
1008      (let recur ((lis lis1))
1009	(if (null-list? lis) lis
1010	    (let ((tail (recur (cdr lis))))
1011	      (cond ((f (car lis)) => (lambda (x) (cons x tail)))
1012		    (else tail)))))))
1013
1014
1015;;; Map F across lists, guaranteeing to go left-to-right.
1016;;; NOTE: Some implementations of R5RS MAP are compliant with this spec;
1017;;; in which case this procedure may simply be defined as a synonym for MAP.
1018
1019(define (map-in-order f lis1 . lists)
1020  (check-arg procedure? f map-in-order)
1021  (if (pair? lists)
1022      (let recur ((lists (cons lis1 lists)))
1023	(receive (cars cdrs) (%cars+cdrs lists)
1024	  (if (pair? cars)
1025	      (let ((x (apply f cars)))		; Do head first,
1026		(cons x (recur cdrs)))		; then tail.
1027	      '())))
1028
1029      ;; Fast path.
1030      (let recur ((lis lis1))
1031	(if (null-list? lis) lis
1032	    (let ((tail (cdr lis))
1033		  (x (f (car lis))))		; Do head first,
1034	      (cons x (recur tail)))))))	; then tail.
1035
1036
1037;;; We extend MAP to handle arguments of unequal length.
1038(define map map-in-order)
1039
1040;; Added by yamaken 2007-06-15
1041(define for-each
1042  (lambda args
1043    (apply map-in-order args)
1044    %srfi-1:undefined))
1045
1046;;; filter, remove, partition
1047;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1048;;; FILTER, REMOVE, PARTITION and their destructive counterparts do not
1049;;; disorder the elements of their argument.
1050
1051;; This FILTER shares the longest tail of L that has no deleted elements.
1052;; If Scheme had multi-continuation calls, they could be made more efficient.
1053
1054(define (filter pred lis)			; Sleazing with EQ? makes this
1055  (check-arg procedure? pred filter)		; one faster.
1056  (let recur ((lis lis))
1057    (if (null-list? lis) lis			; Use NOT-PAIR? to handle dotted lists.
1058	(let ((head (car lis))
1059	      (tail (cdr lis)))
1060	  (if (pred head)
1061	      (let ((new-tail (recur tail)))	; Replicate the RECUR call so
1062		(if (eq? tail new-tail) lis
1063		    (cons head new-tail)))
1064	      (recur tail))))))			; this one can be a tail call.
1065
1066
1067;;; Another version that shares longest tail.
1068;(define (filter pred lis)
1069;  (receive (ans no-del?)
1070;      ;; (recur l) returns L with (pred x) values filtered.
1071;      ;; It also returns a flag NO-DEL? if the returned value
1072;      ;; is EQ? to L, i.e. if it didn't have to delete anything.
1073;      (let recur ((l l))
1074;	(if (null-list? l) (values l #t)
1075;	    (let ((x  (car l))
1076;		  (tl (cdr l)))
1077;	      (if (pred x)
1078;		  (receive (ans no-del?) (recur tl)
1079;		    (if no-del?
1080;			(values l #t)
1081;			(values (cons x ans) #f)))
1082;		  (receive (ans no-del?) (recur tl) ; Delete X.
1083;		    (values ans #f))))))
1084;    ans))
1085
1086
1087
1088;(define (filter! pred lis)			; Things are much simpler
1089;  (let recur ((lis lis))			; if you are willing to
1090;    (if (pair? lis)				; push N stack frames & do N
1091;        (cond ((pred (car lis))		; SET-CDR! writes, where N is
1092;               (set-cdr! lis (recur (cdr lis))); the length of the answer.
1093;               lis)
1094;              (else (recur (cdr lis))))
1095;        lis)))
1096
1097
1098;;; This implementation of FILTER!
1099;;; - doesn't cons, and uses no stack;
1100;;; - is careful not to do redundant SET-CDR! writes, as writes to memory are
1101;;;   usually expensive on modern machines, and can be extremely expensive on
1102;;;   modern Schemes (e.g., ones that have generational GC's).
1103;;; It just zips down contiguous runs of in and out elts in LIS doing the
1104;;; minimal number of SET-CDR!s to splice the tail of one run of ins to the
1105;;; beginning of the next.
1106
1107(define (filter! pred lis)
1108  (check-arg procedure? pred filter!)
1109  (let lp ((ans lis))
1110    (cond ((null-list? ans)       ans)			; Scan looking for
1111	  ((not (pred (car ans))) (lp (cdr ans)))	; first cons of result.
1112
1113	  ;; ANS is the eventual answer.
1114	  ;; SCAN-IN: (CDR PREV) = LIS and (CAR PREV) satisfies PRED.
1115	  ;;          Scan over a contiguous segment of the list that
1116	  ;;          satisfies PRED.
1117	  ;; SCAN-OUT: (CAR PREV) satisfies PRED. Scan over a contiguous
1118	  ;;           segment of the list that *doesn't* satisfy PRED.
1119	  ;;           When the segment ends, patch in a link from PREV
1120	  ;;           to the start of the next good segment, and jump to
1121	  ;;           SCAN-IN.
1122	  (else (letrec ((scan-in (lambda (prev lis)
1123				    (if (pair? lis)
1124					(if (pred (car lis))
1125					    (scan-in lis (cdr lis))
1126					    (scan-out prev (cdr lis))))))
1127			 (scan-out (lambda (prev lis)
1128				     (let lp ((lis lis))
1129				       (if (pair? lis)
1130					   (if (pred (car lis))
1131					       (begin (set-cdr! prev lis)
1132						      (scan-in lis (cdr lis)))
1133					       (lp (cdr lis)))
1134					   (set-cdr! prev lis))))))
1135		  (scan-in ans (cdr ans))
1136		  ans)))))
1137
1138
1139
1140;;; Answers share common tail with LIS where possible;
1141;;; the technique is slightly subtle.
1142
1143(define (partition pred lis)
1144  (check-arg procedure? pred partition)
1145  (let recur ((lis lis))
1146    (if (null-list? lis) (values lis lis)	; Use NOT-PAIR? to handle dotted lists.
1147	(let ((elt (car lis))
1148	      (tail (cdr lis)))
1149	  (receive (in out) (recur tail)
1150	    (if (pred elt)
1151		(values (if (pair? out) (cons elt in) lis) out)
1152		(values in (if (pair? in) (cons elt out) lis))))))))
1153
1154
1155
1156;(define (partition! pred lis)			; Things are much simpler
1157;  (let recur ((lis lis))			; if you are willing to
1158;    (if (null-list? lis) (values lis lis)	; push N stack frames & do N
1159;        (let ((elt (car lis)))			; SET-CDR! writes, where N is
1160;          (receive (in out) (recur (cdr lis))	; the length of LIS.
1161;            (cond ((pred elt)
1162;                   (set-cdr! lis in)
1163;                   (values lis out))
1164;                  (else (set-cdr! lis out)
1165;                        (values in lis))))))))
1166
1167
1168;;; This implementation of PARTITION!
1169;;; - doesn't cons, and uses no stack;
1170;;; - is careful not to do redundant SET-CDR! writes, as writes to memory are
1171;;;   usually expensive on modern machines, and can be extremely expensive on
1172;;;   modern Schemes (e.g., ones that have generational GC's).
1173;;; It just zips down contiguous runs of in and out elts in LIS doing the
1174;;; minimal number of SET-CDR!s to splice these runs together into the result
1175;;; lists.
1176
1177(define (partition! pred lis)
1178  (check-arg procedure? pred partition!)
1179  (if (null-list? lis) (values lis lis)
1180
1181      ;; This pair of loops zips down contiguous in & out runs of the
1182      ;; list, splicing the runs together. The invariants are
1183      ;;   SCAN-IN:  (cdr in-prev)  = LIS.
1184      ;;   SCAN-OUT: (cdr out-prev) = LIS.
1185      (letrec ((scan-in (lambda (in-prev out-prev lis)
1186			  (let lp ((in-prev in-prev) (lis lis))
1187			    (if (pair? lis)
1188				(if (pred (car lis))
1189				    (lp lis (cdr lis))
1190				    (begin (set-cdr! out-prev lis)
1191					   (scan-out in-prev lis (cdr lis))))
1192				(set-cdr! out-prev lis))))) ; Done.
1193
1194	       (scan-out (lambda (in-prev out-prev lis)
1195			   (let lp ((out-prev out-prev) (lis lis))
1196			     (if (pair? lis)
1197				 (if (pred (car lis))
1198				     (begin (set-cdr! in-prev lis)
1199					    (scan-in lis out-prev (cdr lis)))
1200				     (lp lis (cdr lis)))
1201				 (set-cdr! in-prev lis)))))) ; Done.
1202
1203	;; Crank up the scan&splice loops.
1204	(if (pred (car lis))
1205	    ;; LIS begins in-list. Search for out-list's first pair.
1206	    (let lp ((prev-l lis) (l (cdr lis)))
1207	      (cond ((not (pair? l)) (values lis l))
1208		    ((pred (car l)) (lp l (cdr l)))
1209		    (else (scan-out prev-l l (cdr l))
1210			  (values lis l))))	; Done.
1211
1212	    ;; LIS begins out-list. Search for in-list's first pair.
1213	    (let lp ((prev-l lis) (l (cdr lis)))
1214	      (cond ((not (pair? l)) (values l lis))
1215		    ((pred (car l))
1216		     (scan-in l prev-l (cdr l))
1217		     (values l lis))		; Done.
1218		    (else (lp l (cdr l)))))))))
1219
1220
1221;;; Inline us, please.
1222(define (remove  pred l) (filter  (lambda (x) (not (pred x))) l))
1223(define (remove! pred l) (filter! (lambda (x) (not (pred x))) l))
1224
1225
1226
1227;;; Here's the taxonomy for the DELETE/ASSOC/MEMBER functions.
1228;;; (I don't actually think these are the world's most important
1229;;; functions -- the procedural FILTER/REMOVE/FIND/FIND-TAIL variants
1230;;; are far more general.)
1231;;;
1232;;; Function			Action
1233;;; ---------------------------------------------------------------------------
1234;;; remove pred lis		Delete by general predicate
1235;;; delete x lis [=]		Delete by element comparison
1236;;;
1237;;; find pred lis		Search by general predicate
1238;;; find-tail pred lis		Search by general predicate
1239;;; member x lis [=]		Search by element comparison
1240;;;
1241;;; assoc key lis [=]		Search alist by key comparison
1242;;; alist-delete key alist [=]	Alist-delete by key comparison
1243
1244(define (delete x lis . maybe-=)
1245  (let ((= (:optional maybe-= equal?)))
1246    (filter (lambda (y) (not (= x y))) lis)))
1247
1248(define (delete! x lis . maybe-=)
1249  (let ((= (:optional maybe-= equal?)))
1250    (filter! (lambda (y) (not (= x y))) lis)))
1251
1252;;; Extended from R4RS to take an optional comparison argument.
1253(define (member x lis . maybe-=)
1254  (let ((= (:optional maybe-= equal?)))
1255    (find-tail (lambda (y) (= x y)) lis)))
1256
1257;;; R4RS, hence we don't bother to define.
1258;;; The MEMBER and then FIND-TAIL call should definitely
1259;;; be inlined for MEMQ & MEMV.
1260;(define (memq    x lis) (member x lis eq?))
1261;(define (memv    x lis) (member x lis eqv?))
1262
1263
1264;;; right-duplicate deletion
1265;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1266;;; delete-duplicates delete-duplicates!
1267;;;
1268;;; Beware -- these are N^2 algorithms. To efficiently remove duplicates
1269;;; in long lists, sort the list to bring duplicates together, then use a
1270;;; linear-time algorithm to kill the dups. Or use an algorithm based on
1271;;; element-marking. The former gives you O(n lg n), the latter is linear.
1272
1273(define (delete-duplicates lis . maybe-=)
1274  (let ((elt= (:optional maybe-= equal?)))
1275    (check-arg procedure? elt= delete-duplicates)
1276    (let recur ((lis lis))
1277      (if (null-list? lis) lis
1278	  (let* ((x (car lis))
1279		 (tail (cdr lis))
1280		 (new-tail (recur (delete x tail elt=))))
1281	    (if (eq? tail new-tail) lis (cons x new-tail)))))))
1282
1283(define (delete-duplicates! lis . maybe-=)
1284  (let ((elt= (:optional maybe-= equal?)))
1285    (check-arg procedure? elt= delete-duplicates!)
1286    (let recur ((lis lis))
1287      (if (null-list? lis) lis
1288	  (let* ((x (car lis))
1289		 (tail (cdr lis))
1290		 (new-tail (recur (delete! x tail elt=))))
1291	    (if (eq? tail new-tail) lis (cons x new-tail)))))))
1292
1293
1294;;; alist stuff
1295;;;;;;;;;;;;;;;
1296
1297;;; Extended from R4RS to take an optional comparison argument.
1298(define (assoc x lis . maybe-=)
1299  (let ((= (:optional maybe-= equal?)))
1300    (find (lambda (entry) (= x (car entry))) lis)))
1301
1302(define (alist-cons key datum alist) (cons (cons key datum) alist))
1303
1304(define (alist-copy alist)
1305  (map (lambda (elt) (cons (car elt) (cdr elt)))
1306       alist))
1307
1308(define (alist-delete key alist . maybe-=)
1309  (let ((= (:optional maybe-= equal?)))
1310    (filter (lambda (elt) (not (= key (car elt)))) alist)))
1311
1312(define (alist-delete! key alist . maybe-=)
1313  (let ((= (:optional maybe-= equal?)))
1314    (filter! (lambda (elt) (not (= key (car elt)))) alist)))
1315
1316
1317;;; find find-tail take-while drop-while span break any every list-index
1318;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1319
1320(define (find pred list)
1321  (cond ((find-tail pred list) => car)
1322	(else #f)))
1323
1324(define (find-tail pred list)
1325  (check-arg procedure? pred find-tail)
1326  (let lp ((list list))
1327    (and (not (null-list? list))
1328	 (if (pred (car list)) list
1329	     (lp (cdr list))))))
1330
1331(define (take-while pred lis)
1332  (check-arg procedure? pred take-while)
1333  (let recur ((lis lis))
1334    (if (null-list? lis) '()
1335	(let ((x (car lis)))
1336	  (if (pred x)
1337	      (cons x (recur (cdr lis)))
1338	      '())))))
1339
1340(define (drop-while pred lis)
1341  (check-arg procedure? pred drop-while)
1342  (let lp ((lis lis))
1343    (if (null-list? lis) '()
1344	(if (pred (car lis))
1345	    (lp (cdr lis))
1346	    lis))))
1347
1348(define (take-while! pred lis)
1349  (check-arg procedure? pred take-while!)
1350  (if (or (null-list? lis) (not (pred (car lis)))) '()
1351      (begin (let lp ((prev lis) (rest (cdr lis)))
1352	       (if (pair? rest)
1353		   (let ((x (car rest)))
1354		     (if (pred x) (lp rest (cdr rest))
1355			 (set-cdr! prev '())))))
1356	     lis)))
1357
1358(define (span pred lis)
1359  (check-arg procedure? pred span)
1360  (let recur ((lis lis))
1361    (if (null-list? lis) (values '() '())
1362	(let ((x (car lis)))
1363	  (if (pred x)
1364	      (receive (prefix suffix) (recur (cdr lis))
1365		(values (cons x prefix) suffix))
1366	      (values '() lis))))))
1367
1368(define (span! pred lis)
1369  (check-arg procedure? pred span!)
1370  (if (or (null-list? lis) (not (pred (car lis)))) (values '() lis)
1371      (let ((suffix (let lp ((prev lis) (rest (cdr lis)))
1372		      (if (null-list? rest) rest
1373			  (let ((x (car rest)))
1374			    (if (pred x) (lp rest (cdr rest))
1375				(begin (set-cdr! prev '())
1376				       rest)))))))
1377	(values lis suffix))))
1378
1379
1380(define (break  pred lis) (span  (lambda (x) (not (pred x))) lis))
1381(define (break! pred lis) (span! (lambda (x) (not (pred x))) lis))
1382
1383(define (any pred lis1 . lists)
1384  (check-arg procedure? pred any)
1385  (if (pair? lists)
1386
1387      ;; N-ary case
1388      (receive (heads tails) (%cars+cdrs (cons lis1 lists))
1389	(and (pair? heads)
1390	     (let lp ((heads heads) (tails tails))
1391	       (receive (next-heads next-tails) (%cars+cdrs tails)
1392		 (if (pair? next-heads)
1393		     (or (apply pred heads) (lp next-heads next-tails))
1394		     (apply pred heads)))))) ; Last PRED app is tail call.
1395
1396      ;; Fast path
1397      (and (not (null-list? lis1))
1398	   (let lp ((head (car lis1)) (tail (cdr lis1)))
1399	     (if (null-list? tail)
1400		 (pred head)		; Last PRED app is tail call.
1401		 (or (pred head) (lp (car tail) (cdr tail))))))))
1402
1403
1404;(define (every pred list)              ; Simple definition.
1405;  (let lp ((list list))                ; Doesn't return the last PRED value.
1406;    (or (not (pair? list))
1407;        (and (pred (car list))
1408;             (lp (cdr list))))))
1409
1410(define (every pred lis1 . lists)
1411  (check-arg procedure? pred every)
1412  (if (pair? lists)
1413
1414      ;; N-ary case
1415      (receive (heads tails) (%cars+cdrs (cons lis1 lists))
1416	(or (not (pair? heads))
1417	    (let lp ((heads heads) (tails tails))
1418	      (receive (next-heads next-tails) (%cars+cdrs tails)
1419		(if (pair? next-heads)
1420		    (and (apply pred heads) (lp next-heads next-tails))
1421		    (apply pred heads)))))) ; Last PRED app is tail call.
1422
1423      ;; Fast path
1424      (or (null-list? lis1)
1425	  (let lp ((head (car lis1))  (tail (cdr lis1)))
1426	    (if (null-list? tail)
1427		(pred head)	; Last PRED app is tail call.
1428		(and (pred head) (lp (car tail) (cdr tail))))))))
1429
1430(define (list-index pred lis1 . lists)
1431  (check-arg procedure? pred list-index)
1432  (if (pair? lists)
1433
1434      ;; N-ary case
1435      (let lp ((lists (cons lis1 lists)) (n 0))
1436	(receive (heads tails) (%cars+cdrs lists)
1437	  (and (pair? heads)
1438	       (if (apply pred heads) n
1439		   (lp tails (+ n 1))))))
1440
1441      ;; Fast path
1442      (let lp ((lis lis1) (n 0))
1443	(and (not (null-list? lis))
1444	     (if (pred (car lis)) n (lp (cdr lis) (+ n 1)))))))
1445
1446;;; Reverse
1447;;;;;;;;;;;
1448
1449;R4RS, so not defined here.
1450;(define (reverse lis) (fold cons '() lis))
1451
1452;(define (reverse! lis)
1453;  (pair-fold (lambda (pair tail) (set-cdr! pair tail) pair) '() lis))
1454
1455(define (reverse! lis)
1456  (let lp ((lis lis) (ans '()))
1457    (if (null-list? lis) ans
1458        (let ((tail (cdr lis)))
1459          (set-cdr! lis ans)
1460          (lp tail lis)))))
1461
1462;;; Lists-as-sets
1463;;;;;;;;;;;;;;;;;
1464
1465;;; This is carefully tuned code; do not modify casually.
1466;;; - It is careful to share storage when possible;
1467;;; - Side-effecting code tries not to perform redundant writes.
1468;;; - It tries to avoid linear-time scans in special cases where constant-time
1469;;;   computations can be performed.
1470;;; - It relies on similar properties from the other list-lib procs it calls.
1471;;;   For example, it uses the fact that the implementations of MEMBER and
1472;;;   FILTER in this source code share longest common tails between args
1473;;;   and results to get structure sharing in the lset procedures.
1474
1475(define (%lset2<= = lis1 lis2) (every (lambda (x) (member x lis2 =)) lis1))
1476
1477(define (lset<= = . lists)
1478  (check-arg procedure? = lset<=)
1479  (or (not (pair? lists)) ; 0-ary case
1480      (let lp ((s1 (car lists)) (rest (cdr lists)))
1481	(or (not (pair? rest))
1482	    (let ((s2 (car rest))  (rest (cdr rest)))
1483	      (and (or (eq? s2 s1)	; Fast path
1484		       (%lset2<= = s1 s2)) ; Real test
1485		   (lp s2 rest)))))))
1486
1487(define (lset= = . lists)
1488  (check-arg procedure? = lset=)
1489  (or (not (pair? lists)) ; 0-ary case
1490      (let lp ((s1 (car lists)) (rest (cdr lists)))
1491	(or (not (pair? rest))
1492	    (let ((s2   (car rest))
1493		  (rest (cdr rest)))
1494	      (and (or (eq? s1 s2)	; Fast path
1495		       (and (%lset2<= = s1 s2) (%lset2<= = s2 s1))) ; Real test
1496		   (lp s2 rest)))))))
1497
1498
1499(define (lset-adjoin = lis . elts)
1500  (check-arg procedure? = lset-adjoin)
1501  (fold (lambda (elt ans) (if (member elt ans =) ans (cons elt ans)))
1502	lis elts))
1503
1504
1505(define (lset-union = . lists)
1506  (check-arg procedure? = lset-union)
1507  (reduce (lambda (lis ans)		; Compute ANS + LIS.
1508	    (cond ((null? lis) ans)	; Don't copy any lists
1509		  ((null? ans) lis) 	; if we don't have to.
1510		  ((eq? lis ans) ans)
1511		  (else
1512		   (fold (lambda (elt ans) (if (any (lambda (x) (= x elt)) ans)
1513					       ans
1514					       (cons elt ans)))
1515			 ans lis))))
1516	  '() lists))
1517
1518(define (lset-union! = . lists)
1519  (check-arg procedure? = lset-union!)
1520  (reduce (lambda (lis ans)		; Splice new elts of LIS onto the front of ANS.
1521	    (cond ((null? lis) ans)	; Don't copy any lists
1522		  ((null? ans) lis) 	; if we don't have to.
1523		  ((eq? lis ans) ans)
1524		  (else
1525		   (pair-fold (lambda (pair ans)
1526				(let ((elt (car pair)))
1527				  (if (any (lambda (x) (= x elt)) ans)
1528				      ans
1529				      (begin (set-cdr! pair ans) pair))))
1530			      ans lis))))
1531	  '() lists))
1532
1533
1534(define (lset-intersection = lis1 . lists)
1535  (check-arg procedure? = lset-intersection)
1536  (let ((lists (delete lis1 lists eq?))) ; Throw out any LIS1 vals.
1537    (cond ((any null-list? lists) '())		; Short cut
1538	  ((null? lists)          lis1)		; Short cut
1539	  (else (filter (lambda (x)
1540			  (every (lambda (lis) (member x lis =)) lists))
1541			lis1)))))
1542
1543(define (lset-intersection! = lis1 . lists)
1544  (check-arg procedure? = lset-intersection!)
1545  (let ((lists (delete lis1 lists eq?))) ; Throw out any LIS1 vals.
1546    (cond ((any null-list? lists) '())		; Short cut
1547	  ((null? lists)          lis1)		; Short cut
1548	  (else (filter! (lambda (x)
1549			   (every (lambda (lis) (member x lis =)) lists))
1550			 lis1)))))
1551
1552
1553(define (lset-difference = lis1 . lists)
1554  (check-arg procedure? = lset-difference)
1555  (let ((lists (filter pair? lists)))	; Throw out empty lists.
1556    (cond ((null? lists)     lis1)	; Short cut
1557	  ((memq lis1 lists) '())	; Short cut
1558	  (else (filter (lambda (x)
1559			  (every (lambda (lis) (not (member x lis =)))
1560				 lists))
1561			lis1)))))
1562
1563(define (lset-difference! = lis1 . lists)
1564  (check-arg procedure? = lset-difference!)
1565  (let ((lists (filter pair? lists)))	; Throw out empty lists.
1566    (cond ((null? lists)     lis1)	; Short cut
1567	  ((memq lis1 lists) '())	; Short cut
1568	  (else (filter! (lambda (x)
1569			   (every (lambda (lis) (not (member x lis =)))
1570				  lists))
1571			 lis1)))))
1572
1573
1574(define (lset-xor = . lists)
1575  (check-arg procedure? = lset-xor)
1576  (reduce (lambda (b a)			; Compute A xor B:
1577	    ;; Note that this code relies on the constant-time
1578	    ;; short-cuts provided by LSET-DIFF+INTERSECTION,
1579	    ;; LSET-DIFFERENCE & APPEND to provide constant-time short
1580	    ;; cuts for the cases A = (), B = (), and A eq? B. It takes
1581	    ;; a careful case analysis to see it, but it's carefully
1582	    ;; built in.
1583
1584	    ;; Compute a-b and a^b, then compute b-(a^b) and
1585	    ;; cons it onto the front of a-b.
1586	    (receive (a-b a-int-b)   (lset-diff+intersection = a b)
1587	      (cond ((null? a-b)     (lset-difference = b a))
1588		    ((null? a-int-b) (append b a))
1589		    (else (fold (lambda (xb ans)
1590				  (if (member xb a-int-b =) ans (cons xb ans)))
1591				a-b
1592				b)))))
1593	  '() lists))
1594
1595
1596(define (lset-xor! = . lists)
1597  (check-arg procedure? = lset-xor!)
1598  (reduce (lambda (b a)			; Compute A xor B:
1599	    ;; Note that this code relies on the constant-time
1600	    ;; short-cuts provided by LSET-DIFF+INTERSECTION,
1601	    ;; LSET-DIFFERENCE & APPEND to provide constant-time short
1602	    ;; cuts for the cases A = (), B = (), and A eq? B. It takes
1603	    ;; a careful case analysis to see it, but it's carefully
1604	    ;; built in.
1605
1606	    ;; Compute a-b and a^b, then compute b-(a^b) and
1607	    ;; cons it onto the front of a-b.
1608	    (receive (a-b a-int-b)   (lset-diff+intersection! = a b)
1609	      (cond ((null? a-b)     (lset-difference! = b a))
1610		    ((null? a-int-b) (append! b a))
1611		    (else (pair-fold (lambda (b-pair ans)
1612				       (if (member (car b-pair) a-int-b =) ans
1613					   (begin (set-cdr! b-pair ans) b-pair)))
1614				     a-b
1615				     b)))))
1616	  '() lists))
1617
1618
1619(define (lset-diff+intersection = lis1 . lists)
1620  (check-arg procedure? = lset-diff+intersection)
1621  (cond ((every null-list? lists) (values lis1 '()))	; Short cut
1622	((memq lis1 lists)        (values '() lis1))	; Short cut
1623	(else (partition (lambda (elt)
1624			   (not (any (lambda (lis) (member elt lis =))
1625				     lists)))
1626			 lis1))))
1627
1628(define (lset-diff+intersection! = lis1 . lists)
1629  (check-arg procedure? = lset-diff+intersection!)
1630  (cond ((every null-list? lists) (values lis1 '()))	; Short cut
1631	((memq lis1 lists)        (values '() lis1))	; Short cut
1632	(else (partition! (lambda (elt)
1633			    (not (any (lambda (lis) (member elt lis =))
1634				      lists)))
1635			  lis1))))
1636