From ab492c3f7ca2058f96cd56b5a2a7d1c67d9b2741 Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Tue, 12 Jun 2007 03:04:16 +0000 Subject: [PATCH] some doc edits related to sequences and for svn: r6582 --- collects/scribblings/guide/for.scrbl | 69 ++++++++++--------- collects/scribblings/reference/bytes.scrbl | 4 ++ collects/scribblings/reference/data.scrbl | 23 +++++++ .../scribblings/reference/sequences.scrbl | 43 ++++++++---- collects/scribblings/reference/strings.scrbl | 4 ++ 5 files changed, 97 insertions(+), 46 deletions(-) diff --git a/collects/scribblings/guide/for.scrbl b/collects/scribblings/guide/for.scrbl index f800ce515f..a101b020bb 100644 --- a/collects/scribblings/guide/for.scrbl +++ b/collects/scribblings/guide/for.scrbl @@ -16,15 +16,15 @@ Variants of @scheme[for] accumulate iteration results in different ways, but they all have the same syntactic shape. Simplifying, for now, the syntax of @scheme[for] is -@schemeblock[ -(for ([_id _sequence-expr]) - _body-expr) -] +@specform[ +(for ([id sequence-expr] ...) + body ...+) +]{} A @scheme[for] loop iterates through the sequence produced by the @scheme[_sequence-expr]. For each element of the sequence, @scheme[for] binds the element to @scheme[_id], and then it evaluates -the @scheme[_body-expr] for side effects. +the @scheme[_body]s for side effects. @examples[ (for ([i '(1 2 3)]) @@ -34,8 +34,8 @@ the @scheme[_body-expr] for side effects. ] The @scheme[for/list] variant of @scheme[for] is more Scheme-like. It -accumulates @scheme[_body-expr] results into a list, instead of -evaluating @scheme[_body-expr] only for side effects. In more +accumulates @scheme[_body] results into a list, instead of +evaluating @scheme[_body] only for side effects. In more technical terms, @scheme[for/list] implements a @defterm{list comprehension}. @@ -49,14 +49,14 @@ comprehension}. The full syntax of @scheme[for] accomodates multiple sequences to iterate in parallel, and the @scheme[for*] variant nests the iterations instead of running them in parallel. More variants of -@scheme[for] and @scheme[for*] accumulate @scheme[_body-expr] results +@scheme[for] and @scheme[for*] accumulate @scheme[_body] results in different ways. In all of these variants, predicates that prune iterations can be included along with bindings. Before details on the variations of @scheme[for], though, it's best to see the kinds of sequence generators that make interesting examples. -@section{Sequence Constructors} +@section[#:tag "guide:sequences"]{Sequence Constructors} The @scheme[in-range] procedure generates a sequence of numbers, given an optional starting number (which defaults to @scheme[0]), a number @@ -80,7 +80,8 @@ The @scheme[in-naturals] procedure is similar, except that the starting number must be an exact non-negative integer (which defaults to @scheme[0]), the step is always @scheme[1], and there is no upper limit. A @scheme[for] loop using just @scheme[in-naturals] will never -terminate. +terminate unless a body expression raises an exception or otherwise +escapes. @examples[ (for ([i (in-naturals)]) @@ -104,9 +105,9 @@ true. Sequence constructors like @scheme[in-list], @scheme[in-vector] and @scheme[in-string] simply make explicit the use of a list, vector, or string as a sequence. Since they raise an exception when given the -wrong kind of value and otherwise avoid a run-time dispatch to -determine the sequence type, they enable more efficient code -generation; see @secref["for-performance"] for more information. +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. @examples[ (for ([i (in-string "abc")]) @@ -115,19 +116,18 @@ generation; see @secref["for-performance"] for more information. (display i)) ] +@refdetails["mz:sequences"]{sequences} @section{@scheme[for] and @scheme[for*]} -The full syntax of @scheme[for] is +A more complete syntax of @scheme[for] is -@schemeblock[ -(for (_clause ...) - _body-expr ...+) -code:blank -#, @where-is-one-of[@scheme[_clause]] - [_id _sequence-expr] - #:when _boolean-expr -] +@specform/subs[ +(for (clause ...) + body ...+) +([clause [id sequence-expr] + (code:line #:when boolean-expr)]) +]{} When multiple @scheme[[_id _sequence-expr]] clauses are provided in a @scheme[for] form, the corresponding sequences are traversed in @@ -163,7 +163,7 @@ Thus, @scheme[for*] is a shorthand for nested @scheme[for]s in the same way that @scheme[let*] is a shorthand for nested @scheme[let]s. The @scheme[#:when _boolean-expr] form of a @scheme[_clause] is -another shorthand. It allows the @scheme[_body-expr]s to evaluate only +another shorthand. It allows the @scheme[_body]s to evaluate only when the @scheme[_boolean-expr] produces a true value: @interaction[ @@ -191,7 +191,7 @@ mutually nested, instead of in parallel, even with @scheme[for]. @section{@scheme[for/list] and @scheme[for*/list]} The @scheme[for/list] form, which has the same syntax as @scheme[for], -evaluates the @scheme[_body-expr]s to obtain values that go into a +evaluates the @scheme[_body]s to obtain values that go into a newly constructed list: @interaction[ @@ -201,7 +201,7 @@ newly constructed list: ] A @scheme[#:when] clause in a @scheme[for-list] form prunes the result -list along with evaluations of the @scheme[_body-expr]s: +list along with evaluations of the @scheme[_body]s: @interaction[ (for/list ([i (in-naturals 1)] @@ -255,7 +255,7 @@ same facility with nested iterations. @section{@scheme[for/first] and @scheme[for/last]} The @scheme[for/first] form returns the result of the first time that -the @scheme[_body-expr]s are evaluated, skipping further iterations. +the @scheme[_body]s are evaluated, skipping further iterations. This form is most useful with a @scheme[#:when] clause. @interaction[ @@ -264,7 +264,7 @@ This form is most useful with a @scheme[#:when] clause. chapter) ] -If the @scheme[_body-expr]s are evaluated zero time, then the result +If the @scheme[_body]s are evaluated zero time, then the result is @scheme[#f]. The @scheme[for/last] form runs all iterations, returning the value of @@ -301,15 +301,15 @@ beginning: @schemeblock[ (for/fold ([_accum-id _init-expr] ...) (_clause ...) - _body-expr ...+) + _body ...+) ] In the simple case, only one @scheme[[_accum-id _init-expr]] is provided, and the result of the @scheme[for/fold] is the final value for @scheme[_accum-id], which starts out with the value of @scheme[_init-expr]. In the @scheme[_clause]s and -@scheme[_body-expr]s, @scheme[_accum-id] can be referenced to gets its -current value, and the last @scheme[_body-expr] provides the value of +@scheme[_body]s, @scheme[_accum-id] can be referenced to gets its +current value, and the last @scheme[_body] provides the value of @scheme[_accum-id] for the netx iteration. @examples[ @@ -325,7 +325,7 @@ current value, and the last @scheme[_body-expr] provides the value of ] When multiple @scheme[_accum-id]s are specified, then the last -@scheme[_body-expr] must produce multiple values, one for each +@scheme[_body] must produce multiple values, one for each @scheme[_accum-id]. The @scheme[for/fold] expression itself produces multiple values for the results. @@ -350,6 +350,11 @@ In the same way that @scheme[let-values] binds multiple results to multiple identifiers, @scheme[for] can bind multiple sequence elements to multiple iteration identifiers: +@margin-note{While @scheme[let] must be changed to @scheme[let-values] + to bind multiple identifier, @scheme[for] simply allows a + parenthesized list of identifiers instead of a single + identifier in any clause.} + @interaction[ (for ([(k v) #hash(("apple" . 1) ("banana" . 3))]) (printf "~a count: ~a\n" k v)) @@ -431,7 +436,7 @@ fast-parallel-seq (in-parallel fast-seq ...) The grammars above are not complete, because the set of syntactic patterns that provide good performance is extensible, just like the set of sequence values. The documentation for a sequence constructor -should indicate the performance impliciations of using it directly in +should indicate the performance benefits of using it directly in a @scheme[for] @scheme[_clause]. @refdetails["mz:for"]{iterations and comprehensions} diff --git a/collects/scribblings/reference/bytes.scrbl b/collects/scribblings/reference/bytes.scrbl index a114a2341d..30360d00b2 100644 --- a/collects/scribblings/reference/bytes.scrbl +++ b/collects/scribblings/reference/bytes.scrbl @@ -19,6 +19,10 @@ Two byte strings are @scheme[eq?] when mutating one would mutate the other. Two byte strings are @scheme[eqv?] and @scheme[equal?] when they have the same length and contain the same sequence of bytes. +A byte string can be used as a single-valued sequence (see +@secref["mz:sequences"]). The bytes of the string serve as elements +of the sequence. See also @scheme[in-bytes]. + See also: @scheme[immutable]. @; ---------------------------------------- diff --git a/collects/scribblings/reference/data.scrbl b/collects/scribblings/reference/data.scrbl index de63135f5b..85a37e1bed 100644 --- a/collects/scribblings/reference/data.scrbl +++ b/collects/scribblings/reference/data.scrbl @@ -96,6 +96,13 @@ ephemeron key (see @secref["mz:ephemerons"]). @; ---------------------------------------------------------------------- @section[#:tag "mz:pairs"]{Pairs and Lists} +A list can be used as a single-valued sequence (see +@secref["mz:sequences"]). The elements of the list serve as elements +of the sequence. See also @scheme[in-list]. + +@; ---------------------------------------- +@subsection{Pair Constructors, Selectors, and Mutators} + @defproc[(cons [a any/c] [d any/c]) pair?]{Returns a pair whose first element is @scheme[a] and second element is @scheme[d].} @@ -193,12 +200,28 @@ If the @scheme[lst]s are empty, then @scheme[#f] is returned.} @; ------------------------------------------------------------ @section[#:tag "mz:vectors"]{Vectors} +A vector can be used as a single-valued sequence (see +@secref["mz:sequences"]). The elements of the vector serve as elements +of the sequence. See also @scheme[in-vector]. + + @; ------------------------------------------------------------ @section[#:tag "mz:boxes"]{Boxes} @; ---------------------------------------------------------------------- @section[#:tag "mz:hashtables"]{Hash Tables} +A hash table can be used as a two-valued sequence (see +@secref["mz:sequences"]). The keys and values of the hash table serve +as elements of the sequence (i.e., each element is a key and its +associated value). If a mapping is added to or removed from the hash +table during iteration, then an iteration step may fail with +@scheme[exn:fail:contract], or the iteration may skip or duplicate +keys and values. See also @scheme[in-hash-table], +@scheme[in-hash-table-keys], @scheme[in-hash-table-values], and +@scheme[in-hash-table-pairs]. + + @; ---------------------------------------------------------------------- @include-section["sequences.scrbl"] diff --git a/collects/scribblings/reference/sequences.scrbl b/collects/scribblings/reference/sequences.scrbl index 0c2f81aa75..3be528163d 100644 --- a/collects/scribblings/reference/sequences.scrbl +++ b/collects/scribblings/reference/sequences.scrbl @@ -1,29 +1,39 @@ #reader(lib "docreader.ss" "scribble") @require["mz.ss"] +@require-for-syntax[mzscheme] + +@define-syntax[speed + (syntax-rules () + [(_ id what) + @t{A @scheme[id] application can provide better performance for + @elem[what] + iteration when it appears directly in a @scheme[for] clause.}])] @title[#:tag "mz:sequences"]{Sequences} +@guideintro["guide:sequences"]{sequences} + A @pidefterm{sequence} encapsulates an ordered stream of values. The elements of a sequence can be extracted with one of the @scheme[for] syntactic forms or with the procedures returned by @scheme[generate-sequence]. -The datatype overlaps with many other datatypes, because it includes -the following: +The sequence datatype overlaps with many other datatypes. Among +built-in datatypes, the sequence datatype includes the following: @itemize{ - @item{lists; see @secref["mz:pairs"]} + @item{lists (see @secref["mz:pairs"])} - @item{vectors; see @secref["mz:vectors"]} + @item{vectors (see @secref["mz:vectors"])} - @item{hash tables; see @secref["mz:hashtables"]} + @item{hash tables (see @secref["mz:hashtables"])} - @item{strings; see @secref["mz:strings"]} + @item{strings (see @secref["mz:strings"])} - @item{byte strings; see @secref["mz:bytestrings"]} + @item{byte strings (see @secref["mz:bytestrings"])} - @item{input ports; see @secref["mz:input-ports"]} + @item{input ports (see @secref["mz:input-ports"])} } @@ -55,24 +65,29 @@ case @scheme[(in-range end)] is equivalent to @scheme[(in-range 0 end successive element is generated by adding @scheme[step] to the previous element. The sequence starts before an element that would be greater or equal to @scheme[end] if @scheme[step] is non-negative, or -less or equal to @scheme[end] if @scheme[step] is negative.} +less or equal to @scheme[end] if @scheme[step] is negative. +@speed[in-range "number"]} @defproc[(in-naturals [start exact-nonnegative-integer? 0]) sequence?]{ Returns an infinite sequence of exact integers starting with @scheme[start], where each element is one more than the preceeding -element.} +element. @speed[in-naturals "integer"]} @defproc[(in-list [lst list?]) sequence?]{ -Returns a sequence equivalent to @scheme[lst].} +Returns a sequence equivalent to @scheme[lst]. +@speed[in-list "list"]} @defproc[(in-vector [vec vector?]) sequence?]{ -Returns a sequence equivalent to @scheme[vec].} +Returns a sequence equivalent to @scheme[vec]. +@speed[in-vector "vector"]} @defproc[(in-string [str string?]) sequence?]{ -Returns a sequence equivalent to @scheme[str].} +Returns a sequence equivalent to @scheme[str]. +@speed[in-string "string"]} @defproc[(in-bytes [bstr bytes?]) sequence?]{ -Returns a sequence equivalent to @scheme[bstr].} +Returns a sequence equivalent to @scheme[bstr]. +@speed[in-bytes "byte string"]} @defproc[(in-input-port-bytes [inp input-port?]) sequence?]{ Returns a sequence equivalent to @scheme[inp].} diff --git a/collects/scribblings/reference/strings.scrbl b/collects/scribblings/reference/strings.scrbl index b0265b1667..30323f5665 100644 --- a/collects/scribblings/reference/strings.scrbl +++ b/collects/scribblings/reference/strings.scrbl @@ -19,6 +19,10 @@ Two strings are @scheme[eq?] when mutating one would mutate the other. Two strings are @scheme[eqv?] and @scheme[equal?] when they have the same length and contain the same sequence of characters. +A string can be used as a single-valued sequence (see +@secref["mz:sequences"]). The characters of the string serve as elements +of the sequence. See also @scheme[in-string]. + See also: @scheme[immutable], @scheme[symbol->string], @scheme[bytes->string/utf-8].