~ 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