Throw an error if the number input for `take' is too big.

Note that this is usually delayed so it's not too useful.  Note that it
*doesn't* force the list -- see the explanation in the comment.

(Related to PR 11458.)
This commit is contained in:
Eli Barzilay 2010-11-23 14:07:29 -05:00
parent fd53321823
commit 698b3a6c90

View File

@ -575,10 +575,16 @@
;; Extra functionality that is useful for lazy list stuff
(define* (take n l)
(let ([n (! n)] [l (! l)])
(let ([n0 (! n)] [l (! l)])
(if (exact-nonnegative-integer? n)
(let loop ([n n] [l l])
(cond [(or (<= n 0) (null? l)) '()]
(let loop ([n n0] [l l])
(cond [(null? l)
(if (n . > . 0)
;; it would be fine to force the whole list (since we now
;; know it's finite), but doing so means keeping a reference
;; to its head, which can lead to memory leaks.
(error 'take "index ~e too large for input list" n0)
'())]
[(pair? l) (cons (car l) (~ (loop (sub1 n) (! (cdr l)))))]
[else (error 'take "not a proper list: ~e" l)]))
(raise-type-error 'take "non-negative exact integer" 0 n l))))