~ chicken-r7rs (master) fab389daa7aa734a8004a10c9dd399ed1887d79e
commit fab389daa7aa734a8004a10c9dd399ed1887d79e Author: Peter Bex <peter@more-magic.net> AuthorDate: Sun Jul 28 19:00:40 2013 +0000 Commit: Evan Hanson <evhan@foldling.org> CommitDate: Sun Jul 28 19:00:40 2013 +0000 mem*, ass*, list-copy; this completes 6.4: pairs and lists diff --git a/scheme.base-interface.scm b/scheme.base-interface.scm index 3ac77e0..d1062cc 100644 --- a/scheme.base-interface.scm +++ b/scheme.base-interface.scm @@ -8,7 +8,9 @@ append #| apply + |# assoc assq assv + #| begin binary-port? |# @@ -106,11 +108,7 @@ #| library ; for "cond-expand" |# - list - #| - list-copy - |# - list-ref list-set! list-tail list? + list list-copy list-ref list-set! list-tail list? #| make-bytevector |# @@ -121,7 +119,9 @@ make-vector map max min + |# member memq memv + #| modulo remainder negative? positive? newline diff --git a/scheme.base.scm b/scheme.base.scm index e6778a7..393b0d6 100644 --- a/scheme.base.scm +++ b/scheme.base.scm @@ -1,6 +1,6 @@ (module scheme.base () -(import (except scheme syntax-rules cond-expand)) +(import (except scheme syntax-rules cond-expand member)) (import (except chicken with-exception-handler raise)) (include "scheme.base-interface.scm") @@ -165,6 +165,61 @@ (when (null? l) (error 'list-set! "out of range")))) +(: member (forall (a b) (a (list-of b) #!optional (procedure (b a) *) ; sic + -> (or boolean (list-of b))))) + +;; XXX These aren't exported to the types file!? +(define-specialization (member (x (or symbol procedure immediate)) (lst list)) + (##core#inline "C_u_i_memq" x lst)) +(define-specialization (member x (lst (list-of (or symbol procedure immediate)))) + (##core#inline "C_u_i_memq" x lst)) +(define-specialization (member x lst) + (##core#inline "C_i_member" x lst)) + +(define member + (case-lambda + ((x lst) (##core#inline "C_i_member" x lst)) + ((x lst eq?) + (let lp ((lst lst)) + (cond ((null? lst) #f) + ((eq? (car lst) x) lst) + (else (lp (cdr lst)))))))) + + +(: assoc (forall (a b c) (a (list-of (pair b c)) #!optional (procedure (b a) *) ; sic + -> (or boolean (list-of (pair b c)))))) + +;; XXX These aren't exported to the types file!? +(define-specialization (assoc (x (or symbol procedure immediate)) (lst (list-of pair))) + (##core#inline "C_u_i_assq" x lst)) +(define-specialization (assoc x (lst (list-of (pair (or symbol procedure immediate) *)))) + (##core#inline "C_u_i_assq" x lst)) +(define-specialization (assoc x lst) + (##core#inline "C_i_assoc" x lst)) + +(define assoc + (case-lambda + ((x lst) (##core#inline "C_i_assoc" x lst)) + ((x lst eq?) + (let lp ((lst lst)) + (cond ((null? lst) #f) + ((not (pair? (car lst))) + (error 'assoc "unexpected non-pair in list" (car lst))) + ((eq? (caar lst) x) (car lst)) + (else (lp (cdr lst)))))))) + + +(: list-copy (forall (a) ((list-of a) -> (list-of a)))) + +;; TODO: Test if this is the quickest way to do this, or whether we +;; should just cons recursively like our SRFI-1 implementation does. +(define (list-copy lst) + (let lp ((res '()) + (lst lst)) + (if (null? lst) + (##sys#fast-reverse res) + (lp (cons (car lst) res) (cdr lst))))) + ;;; ;;; 6.11. Exceptions ;;; diff --git a/tests/run.scm b/tests/run.scm index 08164b8..6ad6d63 100644 --- a/tests/run.scm +++ b/tests/run.scm @@ -197,7 +197,38 @@ (test '(two three) (cdr ls))) ;; Should be an error? #;(list-set! '(0 1 2) 1 "oops") - )) + (test-error (list-set! (list 1 2 3) 3 'foo))) + + (test-group "mem*" + (test '(a b c) (memq 'a '(a b c))) + (test '(b c) (memq 'b '(a b c))) + (test #f (memq 'a '(b c d))) + (test #f (memq (list 'a) '(b (a) c))) + (test '((a) c) (member (list 'a) '(b (a) c))) + (test '("b" "c") (member "B" '("a" "b" "c") string-ci=?)) + (test '(101 102) (memq 101 '(100 101 102))) ; unspecified in R7RS + (test '(101 102) (memv 101 '(100 101 102)))) + + (test-group "ass*" + (define e '((a 1) (b 2) (c 3))) + (test '(a 1) (assq 'a e)) + (test '(b 2) (assq 'b e)) + (test #f (assq 'd e)) + (test #f (assq (list 'a) '(((a)) ((b)) ((c))))) + (test '((a)) (assoc (list 'a) '(((a)) ((b)) ((c))))) + (test '(2 4) (assoc 2.0 '((1 1) (2 4) (3 9)) =)) + (test '(5 7) (assq 5 '((2 3) (5 7) (11 13)))) ; unspecified in R7RS + (test '(5 7) (assv 5 '((2 3) (5 7) (11 13)))) + (test-error (assq 5 '(5 6 7))) + (test-error (assv 5 '(5 6 7))) + (test-error (assoc 5 '(5 6 7)))) + + (test-group "list-copy" + (define a '(1 8 2 8)) ; a may be immutable + (define b (list-copy a)) + (set-car! b 3) ; b is mutable + (test '((3 8 2 8)) (list b)) + (test '((1 8 2 8)) (list a)))) (define-syntax catch (syntax-rules ()Trap