Make range from racket/list act like in-range when used with for

This commit is contained in:
Alexis King 2017-01-03 12:01:39 -08:00
parent cff1c1dd4e
commit 597661fa4e
2 changed files with 28 additions and 6 deletions

View File

@ -1264,12 +1264,19 @@ predecessor until @racket[end] (excluded) is reached. If no starting
point is provided, @racket[0] is used. If no @racket[step] argument is
provided, @racket[1] is used.
Like @racket[in-range], a @racket[range] application can provide better
performance when it appears directly in a @racket[for] clause.
@mz-examples[#:eval list-eval
(range 10)
(range 10 20)
(range 20 40 2)
(range 20 10 -1)
(range 10 15 1.5)]}
(range 10 15 1.5)]
@history[#:changed "6.7.0.4"
@elem{Adjusted to cooperate with @racket[for] in the same
way that @racket[in-range] does.}]}
@defproc[(append-map [proc procedure?] [lst list?] ...+)

View File

@ -61,6 +61,8 @@
remf
remf*)
(require (for-syntax racket/base))
(define (first x)
(if (and (pair? x) (list? x))
(car x)
@ -561,11 +563,24 @@
(if (pred x) (loop l (cons x i) o) (loop l i (cons x o)))))))
;; similar to in-range, but returns a list
(define range
(case-lambda
[(end) (for/list ([i (in-range end)]) i)]
[(start end) (for/list ([i (in-range start end)]) i)]
[(start end step) (for/list ([i (in-range start end step)]) i)]))
(define range-proc
(let ()
; make sure range has the right runtime name
(define range
(case-lambda
[(end) (for/list ([i (in-range end)]) i)]
[(start end) (for/list ([i (in-range start end)]) i)]
[(start end step) (for/list ([i (in-range start end step)]) i)]))
range))
(define-sequence-syntax range
(λ () #'range-proc)
(λ (stx)
(syntax-case stx ()
[[(n) (_ end)] #'[(n) (in-range end)]]
[[(n) (_ start end)] #'[(n) (in-range start end)]]
[[(n) (_ start end step)] #'[(n) (in-range start end step)]]
[[ids range-expr] #'[ids (#%expression range-expr)]])))
(define append-map
(case-lambda [(f l) (apply append (map f l))]