~ chicken-core (chicken-5) 1b00bdfd5cd3319c26e1ad911caea31803f0bc07


commit 1b00bdfd5cd3319c26e1ad911caea31803f0bc07
Author:     Peter Bex <peter.bex@xs4all.nl>
AuthorDate: Sun May 4 11:27:10 2014 +0200
Commit:     Evan Hanson <evhan@foldling.org>
CommitDate: Mon May 5 07:34:03 2014 +1200

    For consistency, raise an exception from alist-ref when passed a non-list.
    
    Problem reported by Andy Bennett, solution suggested by Evan Hanson.
    
    Signed-off-by: Evan Hanson <evhan@foldling.org>

diff --git a/NEWS b/NEWS
index a7507186..984f771b 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,9 @@
+4.9.1
+
+- Core libraries
+  - alist-ref from unit data-structures now gives an error when passed
+    a non-list, for consistency with assv/assq/assoc.
+
 4.9.0
 
 - Security fixes
diff --git a/data-structures.scm b/data-structures.scm
index 8f62ad9c..51d7e142 100644
--- a/data-structures.scm
+++ b/data-structures.scm
@@ -233,18 +233,22 @@
                           (loop (##sys#slot lst 1))))))))))
 
 (define (alist-ref x lst #!optional (cmp eqv?) (default #f))
-  (let* ([aq (cond [(eq? eq? cmp) assq]
-		   [(eq? eqv? cmp) assv]
-		   [(eq? equal? cmp) assoc]
-		   [else 
+  (let* ((aq (cond ((eq? eq? cmp) assq)
+		   ((eq? eqv? cmp) assv)
+		   ((eq? equal? cmp) assoc)
+		   (else
 		    (lambda (x lst)
-		      (let loop ([lst lst])
-			(and (pair? lst)
-			     (let ([a (##sys#slot lst 0)])
-			       (if (and (pair? a) (cmp (##sys#slot a 0) x))
-				   a
-				   (loop (##sys#slot lst 1)) ) ) ) ) ) ] ) ] 
-	 [item (aq x lst)] )
+		      (let loop ((lst lst))
+			(cond
+			 ((null? lst) #f)
+			 ((pair? lst)
+			  (let ((a (##sys#slot lst 0)))
+			    (##sys#check-pair a 'alist-ref)
+			    (if (cmp (##sys#slot a 0) x)
+				a
+				(loop (##sys#slot lst 1)) ) ))
+			 (else (error 'alist-ref "bad argument type" lst)) )  ) ) ) ) )
+	 (item (aq x lst)) )
     (if item
 	(##sys#slot item 1)
 	default) ) )
diff --git a/tests/data-structures-tests.scm b/tests/data-structures-tests.scm
index 8c160a82..51c25a9e 100644
--- a/tests/data-structures-tests.scm
+++ b/tests/data-structures-tests.scm
@@ -7,6 +7,20 @@
     ((_ expr)
      (assert (handle-exceptions _ #t expr #f)))))
 
+(assert (equal? 'bar (alist-ref 'foo '((foo . bar)))))
+(assert (not (alist-ref 'foo '())))
+(assert (not (alist-ref 'foo '((bar . foo)))))
+(assert-error (alist-ref 'foo 'bar))
+(assert-error (alist-ref 'foo '(bar)))
+
+(let ((cmp (lambda (x y) (eqv? x y))))
+  (assert (equal? 'bar (alist-ref 'foo '((foo . bar)) cmp)))
+  (assert (not (alist-ref 'foo '() cmp)))
+  (assert (not (alist-ref 'foo '((bar . foo)) cmp)))
+  (assert-error (alist-ref 'foo 'bar cmp))
+  (assert-error (alist-ref 'foo '(bar) cmp)))
+
+
 (let ((alist '((foo . 123) ("bar" . "baz"))))
   (alist-update! 'foo 999 alist)
   (assert (= (alist-ref 'foo alist) 999))
Trap