(library (rnrs lists (6))
(export find for-all exists
filter partition
fold-left fold-right
remp remove remv remq
memp member memv memq
assp assoc assv assq
cons*)
(import (rnrs base)
(only (rnrs control) case-lambda))
(define (find f list)
(assert (procedure? f))
(let loop ((l list))
(if (null? l)
#f
(and
(assert (pair? l))
(let ((a (car l)))
(if (f a) a (loop (cdr l))))))))
(define (andmap f l)
(or (null? l)
(and (f (car l))
(andmap f (cdr l)))))
(define (ormap f l)
(and (not (null? l))
(or (f (car l))
(ormap f (cdr l)))))
(define-syntax define-quantifier
(syntax-rules ()
((define-quantifier name base combine)
(define (name f . lists)
(assert (procedure? f))
(let loop ((lists lists))
(if (andmap null? lists)
base
(let ()
(assert (andmap pair? lists))
(let ((cdrs (map cdr lists)))
(if (andmap null? cdrs)
(apply f (map car lists))
(combine (apply f (map car lists))
(loop cdrs)))))))))))
(define-quantifier for-all #t and)
(define-quantifier exists #f or)
(define (filter f list)
(call-with-values
(lambda ()
(partition f list))
(lambda (take leave) take)))
(define (partition f list)
(if (null? list)
(values '() '())
(call-with-values
(lambda ()
(partition f (cdr list)))
(lambda (take leave)
(if (f (car list))
(values (cons (car list) take) leave)
(values take (cons (car list) leave)))))))
(define (mapadd f l last)
(let loop ((l l))
(if (null? l)
(list last)
(cons (f (car l)) (loop (cdr l))))))
(define fold-left
(case-lambda
((f init l)
(let loop ((init init) (l l))
(if (null? l) init (loop (f (car l) init) (cdr l)))))
((f init l . ls)
(let loop ((init init) (ls (cons l ls)))
(cond ((andmap pair? ls)
(loop (apply f (mapadd car ls init)) (map cdr ls)))
((ormap pair? ls)
(error 'fold-left "received non-equal length input lists"))
(else init))))))
(define fold-right
(case-lambda
((f init l)
(let loop ((init init) (l l))
(if (null? l)
init
(f (car l) (loop init (cdr l))))))
((f init l . ls)
(let loop ((ls (cons l ls)))
(cond ((andmap pair? ls)
(apply f (mapadd car ls (loop (map cdr ls)))))
((ormap pair? ls)
(error 'foldr "received non-equal length input lists"))
(else init))))))
(define (remp proc list)
(assert (list? list))
(let loop ((list list))
(if (null? list)
'()
(if (proc (car list))
(cons (car list)
(loop (cdr list)))
(loop (cdr list))))))
(define (remove obj list)
(remp (lambda (x) (equal? x obj)) list))
(define (remv obj list)
(remp (lambda (x) (eqv? x obj)) list))
(define (remq obj list)
(remp (lambda (x) (eq? x obj)) list))
(define (memp proc list)
(let loop ((list list))
(if (null? list)
#f
(and (assert (pair? list))
(if (proc (car list))
list
(loop (cdr list)))))))
(define (member obj list)
(memp (lambda (x) (equal? obj x)) list))
(define (memv obj list)
(memp (lambda (x) (eqv? obj x)) list))
(define (memq obj list)
(memp (lambda (x) (eq? obj x)) list))
(define (assp proc alist)
(let loop ((alist alist))
(if (null? alist)
#f
(and (assert (and (pair? alist)
(pair? (car alist))))
(if (proc (caar alist))
(car alist)
(loop (cdr alist)))))))
(define (assoc obj alist)
(assp (lambda (x) (equal? obj x)) alist))
(define (assv obj alist)
(assp (lambda (x) (eqv? obj x)) alist))
(define (assq obj alist)
(assp (lambda (x) (eq? obj x)) alist))
(define cons*
(case-lambda
((obj) obj)
((obj . objs)
(cons obj (apply cons* objs)))))
)