Make `take' less forceful -- so now (take 0 (error "foo")) returns '()

instead of throwing an error.
This commit is contained in:
Eli Barzilay 2011-01-26 15:51:23 -05:00
parent d2c2112ebc
commit 40610643bf

View File

@ -575,22 +575,20 @@
;; Extra functionality that is useful for lazy list stuff
(define* (take n l)
(let ([n0 (! n)] [l (! l)])
(if (exact-nonnegative-integer? n)
(let ([n0 (! n)])
(unless (exact-nonnegative-integer? n)
(raise-type-error 'take "non-negative exact integer" 0 n l))
(let loop ([n n0] [l l])
(if (zero? n)
'()
(let ([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)
(if (zero? n)
'()
(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))))
(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)]))))))
;; not like Haskell's `cycle' that consumes a list
(define* (cycle . l)