- Hacked append-reverse! so that it won't blow up on improper lists.

- Hacked delete so that it shares storage when possible -- it doesn't
  always copy the entire list. For example, (delete lis (lambda (x) #f))
  returns lis, allocating no new list structure. (It allocates stack frames,
  of course.)
This commit is contained in:
shivers 1998-05-02 17:21:09 +00:00
parent 29c3ebf99a
commit 878c07f4c1
1 changed files with 27 additions and 16 deletions

View File

@ -170,23 +170,34 @@
(define (delq thing list)
(delete (lambda (x) (eq? x thing)) list))
(define (delete pred in-list)
(let loop ((list in-list) (res '()))
(cond ((null? list)
in-list)
((pred (car list))
(append-reverse! res (cdr list)))
(else
(loop (cdr list) (cons (car list) res))))))
(define (append-reverse! l1 l2)
(let loop ((list l1) (res l2))
(cond ((null? list)
res)
(else
(let ((next (cdr list)))
(set-cdr! list res)
(loop next list))))))
(if (pair? list)
(let ((next (cdr list)))
(set-cdr! list res)
(loop next list))
res)))
;; This DELETE shares the longest tail of L that has no deleted elements.
;; If we had multi-continuation calls, this could be made more efficient.
(define (delete pred l)
(call-with-values (lambda ()
;; (recur l) returns L with (pred x) values deleted.
;; It also returns a flag NO-DEL? if the returned value
;; is EQ? to L, i.e. if it didn't delete anything.
(let recur ((l l))
(if (pair? l)
(let ((x (car l))
(tl (cdr l)))
(if (pred x)
(call-with-values (lambda () (recur tl))
(lambda (ans no-del?)
(values ans #f))) ; Deleted X.
(call-with-values (lambda () (recur tl))
(lambda (ans no-del?)
(if no-del?
(values l #t)
(values (cons x ans) #f))))))
(values '() #t))))
(lambda (ans no-del?) ans)))