some doc edits related to sequences and for

svn: r6582
This commit is contained in:
Matthew Flatt 2007-06-12 03:04:16 +00:00
parent 05607ad661
commit ab492c3f7c
5 changed files with 97 additions and 46 deletions

View File

@ -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}

View File

@ -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].
@; ----------------------------------------

View File

@ -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"]

View File

@ -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].}

View File

@ -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].