From e0d26d88b6a16370796e926e8d4cfe2c018c220d Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Mon, 18 Apr 2011 14:54:42 -0600 Subject: [PATCH] support exact nonnegative integers as sequences --- collects/racket/private/for.rkt | 7 ++++++- collects/racket/sequence.rkt | 1 + collects/scribblings/guide/for.scrbl | 15 ++++++++++++--- collects/scribblings/reference/sequences.scrbl | 6 ++++++ collects/tests/racket/for.rktl | 6 +++++- collects/tests/racket/sequence.rktl | 16 +++++++++++----- doc/release-notes/racket/HISTORY.txt | 3 +++ 7 files changed, 44 insertions(+), 10 deletions(-) diff --git a/collects/racket/private/for.rkt b/collects/racket/private/for.rkt index 5e1712ee04..e766a4a3a3 100644 --- a/collects/racket/private/for.rkt +++ b/collects/racket/private/for.rkt @@ -424,7 +424,8 @@ v))) (define (sequence? v) - (or (do-sequence? v) + (or (exact-nonnegative-integer? v) + (do-sequence? v) (sequence-via-prop? v) (stream? v) (mpair? v) @@ -437,6 +438,7 @@ (define (make-sequence who v) (cond + [(exact-nonnegative-integer? v) (:integer-gen v)] [(do-sequence? v) ((do-sequence-ref v 0))] [(mpair? v) (:mlist-gen v)] [(list? v) (:list-gen v)] @@ -498,6 +500,9 @@ [inc (lambda (x) (+ x step))]) (make-range a inc cont?))])) + (define (:integer-gen v) + (values values add1 0 (lambda (i) (i . < . v)) #f #f)) + (define in-naturals (case-lambda [() (in-naturals 0)] diff --git a/collects/racket/sequence.rkt b/collects/racket/sequence.rkt index 087a558c45..6e420a43a1 100644 --- a/collects/racket/sequence.rkt +++ b/collects/racket/sequence.rkt @@ -59,6 +59,7 @@ (cond [(zero? i) seq] [(stream? seq) (stream-tail seq i)] + [(exact-nonnegative-integer? seq) (stream-tail (in-range seq) i)] [else (make-do-sequence (lambda () diff --git a/collects/scribblings/guide/for.scrbl b/collects/scribblings/guide/for.scrbl index bdfbb9f36f..481fc40f27 100644 --- a/collects/scribblings/guide/for.scrbl +++ b/collects/scribblings/guide/for.scrbl @@ -29,6 +29,8 @@ the @racket[_body]s for side effects. (display i)) (for ([i "abc"]) (printf "~a..." i)) +(for ([i 4]) + (display i)) ] The @racket[for/list] variant of @racket[for] is more Racket-like. It @@ -42,6 +44,8 @@ comprehension}. (* i i)) (for/list ([i "abc"]) i) +(for/list ([i 4]) + i) ] The full syntax of @racket[for] accommodates multiple sequences to @@ -59,9 +63,12 @@ see the kinds of sequence generators that make interesting examples. The @racket[in-range] function generates a sequence of numbers, given an optional starting number (which defaults to @racket[0]), a number before which the sequences ends, and an optional step (which defaults -to @racket[1]). +to @racket[1]). Using a non-negative integer @racket[_k] directly as +a sequence is a shorthand for @racket[(in-range _k)]. @examples[ +(for ([i 3]) + (display i)) (for ([i (in-range 3)]) (display i)) (for ([i (in-range 1 4)]) @@ -102,7 +109,8 @@ true. Sequence constructors like @racket[in-list], @racket[in-vector] and @racket[in-string] simply make explicit the use of a list, vector, or -string as a sequence. Since they raise an exception when given the +string as a sequence. Along with @racket[in-range], +these constructors raise an exception when given the wrong kind of value, and since they otherwise avoid a run-time dispatch to determine the sequence type, they enable more efficient code generation; see @secref["for-performance"] for more information. @@ -425,7 +433,8 @@ fast-clause [id fast-seq] @racketgrammar[ #:literals [in-range in-naturals in-list in-vector in-string in-bytes in-value stop-before stop-after] -fast-seq (in-range expr expr) +fast-seq (in-range expr) + (in-range expr expr) (in-range expr expr expr) (in-naturals) (in-naturals expr) diff --git a/collects/scribblings/reference/sequences.scrbl b/collects/scribblings/reference/sequences.scrbl index d5d262513d..38a67c0eee 100644 --- a/collects/scribblings/reference/sequences.scrbl +++ b/collects/scribblings/reference/sequences.scrbl @@ -35,6 +35,8 @@ built-in datatypes, the sequence datatype includes the following: @itemize[ + @item{exact nonnegative integers (see below)} + @item{strings (see @secref["strings"])} @item{byte strings (see @secref["bytestrings"])} @@ -57,6 +59,10 @@ built-in datatypes, the sequence datatype includes the following: ] +An @tech{exact number} @racket[_k] that is a non-negative +@tech{integer} acts as a sequence similar to @racket[(in-range _k)], +except that @racket[_k] by itself is not a @tech{stream}. + The @scheme[make-do-sequence] function creates a sequence given a thunk that returns procedures to implement a sequence, and the @scheme[prop:sequence] property can be associated with a structure diff --git a/collects/tests/racket/for.rktl b/collects/tests/racket/for.rktl index b646b0e0bc..8d410676fb 100644 --- a/collects/tests/racket/for.rktl +++ b/collects/tests/racket/for.rktl @@ -6,9 +6,13 @@ (require racket/mpair "for-util.rkt") +(test-sequence [(0 1 2)] 3) (test-sequence [(0 1 2)] (in-range 3)) (test-sequence [(3 4 5)] (in-range 3 6)) (test-sequence [(7 6 5)] (in-range 7 4 -1)) +(test-sequence [(3.0 4.0 5.0)] (in-range 3.0 6.0)) +(test-sequence [(3.0 3.5 4.0 4.5 5.0 5.5)] (in-range 3.0 6.0 0.5)) +(test-sequence [(3.0 3.1 3.2)] (in-range 3.0 3.3 0.1)) (test-sequence [(a b c)] '(a b c)) (test-sequence [(a b c)] (in-list '(a b c))) @@ -228,7 +232,7 @@ (test 13 next) (test #f more?)) -;; check ranges on `in-vetcor', especially as a value +;; check ranges on `in-vector', especially as a value (test '() 'in-empty-vector (let ([v (in-vector '#())]) (for/list ([e v]) e))) (test '() 'in-empty-vector (let ([v (in-vector '#() 0)]) (for/list ([e v]) e))) (test '() 'in-empty-vector (let ([v (in-vector '#() 0 0)]) (for/list ([e v]) e))) diff --git a/collects/tests/racket/sequence.rktl b/collects/tests/racket/sequence.rktl index 7752da274d..a03bd95bd2 100644 --- a/collects/tests/racket/sequence.rktl +++ b/collects/tests/racket/sequence.rktl @@ -29,21 +29,23 @@ (test '(0 1 2) 'sequence->list (sequence->list (in-range 3))) (arity-test sequence->list 1 1) - (err/rt-test (sequence->list 1)) + (err/rt-test (sequence->list 'a)) (test '() 'empty-sequence (sequence->list empty-sequence)) (arity-test sequence-length 1 1) - (err/rt-test (sequence-length 1)) + (err/rt-test (sequence-length 'a)) (test 3 'sequence-length (sequence-length (in-range 3))) (arity-test sequence-ref 2 2) - (err/rt-test (sequence-ref 2 0)) + (err/rt-test (sequence-ref 'a 0)) (err/rt-test (sequence-ref (in-naturals) -1) exn:fail?) (err/rt-test (sequence-ref (in-naturals) 1.0) exn:fail?) (test 0 'sequence-ref (sequence-ref (in-naturals) 0)) (test 1 'sequence-ref (sequence-ref (in-naturals) 1)) (test 25 'sequence-ref (sequence-ref (in-naturals) 25)) + (when (sequence? 10) + (test 3 sequence-ref 10 3)) (arity-test sequence-tail 2 2) (err/rt-test (sequence-tail (in-naturals) -1) exn:fail?) @@ -51,14 +53,18 @@ (test 4 'sequence-ref (sequence-ref (sequence-tail (in-naturals) 4) 0)) (test 5 'sequence-ref (sequence-ref (sequence-tail (in-naturals) 4) 1)) (test 29 'sequence-ref (sequence-ref (sequence-tail (in-naturals) 4) 25)) + (when (sequence? 10) + (test 29 'sequence-ref (sequence-ref (sequence-tail 100 4) 25))) ;; XXX Check for rest - (err/rt-test (sequence-append 1) exn:fail?) - (err/rt-test (sequence-append (in-naturals) 1) exn:fail?) + (err/rt-test (sequence-append 'a) exn:fail?) + (err/rt-test (sequence-append (in-naturals) 'a) exn:fail?) (test '() 'sequence-append (sequence->list (sequence-append))) (test 5 'sequence-append (sequence-ref (sequence-append (in-naturals)) 5)) (test 5 'sequence-append (sequence-ref (sequence-append (in-range 3) (in-range 3 10)) 5)) + (when (sequence? 10) + (test 5 sequence-ref (sequence-append 4 10) 9)) (arity-test sequence-map 2 2) (err/rt-test (sequence-map 2 (in-naturals)) exn:fail?) diff --git a/doc/release-notes/racket/HISTORY.txt b/doc/release-notes/racket/HISTORY.txt index 19dbae47b5..56144a51c6 100644 --- a/doc/release-notes/racket/HISTORY.txt +++ b/doc/release-notes/racket/HISTORY.txt @@ -1,3 +1,6 @@ +Version 5.1.1.2 +Changed "sequence" to include exact nonnegative integers + Version 5.1.1, May 2011 Enabled single-precision floats by default Added single-flonum?