diff --git a/collects/racket/private/for.rkt b/collects/racket/private/for.rkt index 585324b6b1..6b63210598 100644 --- a/collects/racket/private/for.rkt +++ b/collects/racket/private/for.rkt @@ -29,6 +29,7 @@ (rename *in-range in-range) (rename *in-naturals in-naturals) (rename *in-list in-list) + (rename *in-mlist in-mlist) (rename *in-vector in-vector) (rename *in-string in-string) (rename *in-bytes in-bytes) @@ -318,6 +319,7 @@ (define (sequence? v) (or (do-sequence? v) (list? v) + (mpair? v) (vector? v) (string? v) (bytes? v) @@ -329,6 +331,7 @@ (cond [(do-sequence? v) ((do-sequence-ref v 0))] [(list? v) (:list-gen v)] + [(mpair? v) (:mlist-gen v)] [(vector? v) (:vector-gen v 0 (vector-length v) 1)] [(string? v) (:string-gen v 0 (string-length v) 1)] [(bytes? v) (:bytes-gen v 0 (bytes-length v) 1)] @@ -378,9 +381,15 @@ (define (in-list l) ;; (unless (list? l) (raise-type-error 'in-list "list" l)) (make-do-sequence (lambda () (:list-gen l)))) - + (define (:list-gen l) (values car cdr l pair? void void)) + + (define (in-mlist l) + (make-do-sequence (lambda () (:mlist-gen l)))) + + (define (:mlist-gen l) + (values mcar mcdr l mpair? void void)) (define (check-ranges who start stop step) (unless (exact-nonnegative-integer? start) (raise-type-error who "exact non-negative integer" start)) @@ -1073,6 +1082,31 @@ ;; loop args -- ok to use unsafe-cdr, since car passed ((unsafe-cdr lst)))]] [_ #f]))) + + (define-sequence-syntax *in-mlist + (lambda () #'in-mlist) + (lambda (stx) + (syntax-case stx () + [[(id) (_ lst-expr)] + #'[(id) + (:do-in + ;;outer bindings + ([(lst) lst-expr]) + ;; outer check + (void) ; (unless (list? lst) (in-list lst)) + ;; loop bindings + ([lst lst]) + ;; pos check + (not (null? lst)) + ;; inner bindings + ([(id) (mcar lst)]) + ;; pre guard + #t + ;; post guard + #t + ;; loop args + ((mcdr lst)))]] + [_ #f]))) (define-for-syntax (vector-like-gen vector?-id unsafe-vector-length-id diff --git a/collects/scribblings/reference/dicts.scrbl b/collects/scribblings/reference/dicts.scrbl index adf4ec4093..a96761a276 100644 --- a/collects/scribblings/reference/dicts.scrbl +++ b/collects/scribblings/reference/dicts.scrbl @@ -24,6 +24,10 @@ values. The following datatypes are all dictionaries: ] +A dictionary can be used as a two-valued sequence (see +@secref["sequences"]). The associations of the dictionary serve as elements +of the sequence. See also @scheme[in-dict], @scheme[in-dict-keys], and @scheme[in-dict-values]. + @note-lib[racket/dict] @defproc[(dict? [v any/c]) boolean?]{ diff --git a/collects/scribblings/reference/mpairs.scrbl b/collects/scribblings/reference/mpairs.scrbl index 84932339ac..8f879b5885 100644 --- a/collects/scribblings/reference/mpairs.scrbl +++ b/collects/scribblings/reference/mpairs.scrbl @@ -20,6 +20,10 @@ list. Instead of programming with mutable pairs and mutable lists, data structures such as pairs, lists, and hash tables are practically always better choices. +A @tech{mutable list} can be used as a single-valued sequence (see +@secref["sequences"]). The elements of the @tech{mutable list} serve as elements +of the sequence. See also @scheme[in-mlist]. + @; ---------------------------------------- @section{Mutable Pair Constructors and Selectors} diff --git a/collects/scribblings/reference/sequences.scrbl b/collects/scribblings/reference/sequences.scrbl index 27a159e00c..fadbd178dd 100644 --- a/collects/scribblings/reference/sequences.scrbl +++ b/collects/scribblings/reference/sequences.scrbl @@ -2,7 +2,8 @@ @(require "mz.ss" (for-syntax racket/base) scribble/scheme - (for-label racket/generator)) + (for-label racket/generator + racket/mpair)) @(define generator-eval (lambda () @@ -27,15 +28,21 @@ built-in datatypes, the sequence datatype includes the following: @itemize[ + @item{strings (see @secref["strings"])} + + @item{byte strings (see @secref["bytestrings"])} + @item{lists (see @secref["pairs"])} + @item{mutable lists (see @secref["mpairs"])} + @item{vectors (see @secref["vectors"])} @item{hash tables (see @secref["hashtables"])} - @item{strings (see @secref["strings"])} + @item{dictionaries (see @secref["dicts"])} - @item{byte strings (see @secref["bytestrings"])} + @item{sets (see @secref["sets"])} @item{input ports (see @secref["ports"])} @@ -167,6 +174,11 @@ Returns a sequence equivalent to @scheme[lst]. @info-on-seq["pairs" "lists"] @speed[in-list "list"]} +@defproc[(in-mlist [mlst mlist?]) sequence?]{ +Returns a sequence equivalent to @scheme[mlst]. +@info-on-seq["mpairs" "mutable lists"] +@speed[in-mlist "mutable list"]} + @defproc[(in-vector [vec vector?] [start exact-nonnegative-integer? 0] [stop (or/c exact-nonnegative-integer? #f) #f] diff --git a/collects/scribblings/reference/sets.scrbl b/collects/scribblings/reference/sets.scrbl index 358ca31364..282debdbe1 100644 --- a/collects/scribblings/reference/sets.scrbl +++ b/collects/scribblings/reference/sets.scrbl @@ -8,14 +8,16 @@ A @deftech{set} represents a set of distinct elements. For a given set, elements are equivalent via @scheme[equal?], @scheme[eqv?], or @scheme[eq?]. Two sets are @scheme[equal?] when they use the same element-comparison procedure (@scheme[equal?], @scheme[eqv?], or -@scheme[eq?]) and have equivalent elements. A set can be used as a -@tech{sequence} (see @secref["sequences"]). +@scheme[eq?]) and have equivalent elements. + +A set can be used as a single-valued sequence (see +@secref["sequences"]). The elements of the set serve as elements +of the sequence. See also @scheme[in-set]. Operations on sets that contain elements that are mutated are unpredictable in much the same way that @tech{hash table} operations are unpredictable when keys are mutated. - @note-lib[racket/set] @defproc[(set? [v any/c]) boolean?]{ diff --git a/collects/tests/racket/for.rktl b/collects/tests/racket/for.rktl index db1c46c3e0..675b9724ff 100644 --- a/collects/tests/racket/for.rktl +++ b/collects/tests/racket/for.rktl @@ -3,7 +3,8 @@ (Section 'for) -(require scheme/generator) +(require scheme/generator + racket/mpair) (define-syntax (test-multi-generator stx) (syntax-case stx () @@ -105,6 +106,8 @@ (test-generator [(a b c)] '(a b c)) (test-generator [(a b c)] (in-list '(a b c))) +(test-generator [(a b c)] (mlist 'a 'b 'c)) +(test-generator [(a b c)] (in-mlist (mlist 'a 'b 'c))) (test-generator [(a b c)] #(a b c)) (test-generator [(a b c)] (in-vector #(a b c))) (test-generator [(b c d)] (in-vector #(a b c d) 1))