~ 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