reference-manual work

svn: r6480
This commit is contained in:
Matthew Flatt 2007-06-05 06:44:39 +00:00
parent d98743e1e9
commit eeaa856ff1
12 changed files with 572 additions and 125 deletions

View File

@ -137,12 +137,14 @@
;; ----------------------------------------
(provide defproc defproc* defstruct defthing defform defform/none
(provide defproc defproc* defstruct defthing defform defform* defform/none
specsubform specsubform/inline
var svar void-const)
var svar void-const undefined-const)
(define (void-const)
(schemefont "#<void>"))
(define void-const
(schemeresultfont "#<void>"))
(define undefined-const
(schemeresultfont "#<undefined>"))
(define dots0
(make-element #f (list "...")))
@ -161,9 +163,9 @@
(syntax-rules ()
[(_ name fields desc ...)
(*defstruct 'name 'fields (lambda () (list desc ...)))]))
(define-syntax (defform stx)
(define-syntax (defform* stx)
(syntax-case stx ()
[(_ spec desc ...)
[(_ [spec spec1 ...] desc ...)
(with-syntax ([new-spec
(syntax-case #'spec ()
[(name . rest)
@ -174,11 +176,17 @@
#'name)
#'rest)
#'spec)])])
#'(*defform #t 'spec (lambda (x) (schemeblock0 new-spec)) (lambda () (list desc ...))))]))
#'(*defforms #t '(spec spec1 ...)
(list (lambda (x) (schemeblock0 new-spec))
(lambda (ignored) (schemeblock0 spec1)) ...)
(lambda () (list desc ...))))]))
(define-syntax (defform stx)
(syntax-case stx ()
[(_ spec desc ...) #'(defform* [spec] desc ...)]))
(define-syntax (defform/none stx)
(syntax-case stx ()
[(_ spec desc ...)
#'(*defform #f 'spec (lambda (ignored) (schemeblock0 spec)) (lambda () (list desc ...)))]))
#'(*defforms #f '(spec) (list (lambda (ignored) (schemeblock0 spec))) (lambda () (list desc ...)))]))
(define-syntax specsubform
(syntax-rules ()
[(_ spec desc ...)
@ -383,35 +391,42 @@
(define (meta-symbol? s) (memq s '(... ...+ ?)))
(define (*defform kw? form form-proc content-thunk)
(define (*defforms kw? forms form-procs content-thunk)
(parameterize ([current-variable-list
(let loop ([form (if kw? (cdr form) form)])
(cond
[(symbol? form) (if (meta-symbol? form)
null
(list form))]
[(pair? form) (append (loop (car form))
(loop (cdr form)))]
[else null]))])
(apply
append
(map (lambda (form)
(let loop ([form (if kw? (cdr form) form)])
(cond
[(symbol? form) (if (meta-symbol? form)
null
(list form))]
[(pair? form) (append (loop (car form))
(loop (cdr form)))]
[else null])))
forms))])
(make-splice
(cons
(make-table
'boxed
(list
(list (make-flow
(list
((or form-proc
(lambda (x)
(make-paragraph
(list
(to-element
`(,x
. ,(cdr form)))))))
(and kw?
(make-target-element
#f
(list (to-element (car form)))
(register-scheme-form-definition (car form))))))))))
(map (lambda (form form-proc)
(list
(make-flow
(list
((or form-proc
(lambda (x)
(make-paragraph
(list
(to-element
`(,x
. ,(cdr form)))))))
(and kw?
(eq? form (car forms))
(make-target-element
#f
(list (to-element (car form)))
(register-scheme-form-definition (car form)))))))))
forms form-procs))
(content-thunk)))))
(define (*specsubform form form-thunk content-thunk)

View File

@ -28,19 +28,19 @@
(define opt-color "schemeopt")
(define current-keyword-list
(make-parameter '(define let let* letrec require provide let-values
lambda new send if cond begin else and or
(make-parameter '(define require provide
new send if cond begin else and or
define-syntax syntax-rules define-struct
quote quasiquote unquote unquote-splicing
syntax quasisyntax unsyntax unsyntax-splicing
for/fold for/list for*/list for for/and for/or for* for*/or for*/and for*/fold
for-values for*/list-values for/first for/last
set!)))
(define current-variable-list
(make-parameter null))
(define defined-names (make-hash-table))
(define-struct (sized-element element) (length))
(define (typeset c multi-line? prefix1 prefix color?)
(let* ([c (syntax-ize c 0)]
[content null]
@ -63,7 +63,10 @@
(define out
(case-lambda
[(v cls)
(out v cls (if (string? v) (string-length v) 1))]
(out v cls (cond
[(string? v) (string-length v)]
[(sized-element? v) (sized-element-length v)]
[else 1]))]
[(v cls len)
(unless (equal? v "")
(if (equal? v "\n")
@ -125,12 +128,13 @@
(datum->syntax-object
a
(let ([val? (positive? quote-depth)])
(make-element
(make-sized-element
(if val? value-color #f)
(list
(make-element (if val? value-color paren-color) '(". "))
(typeset a #f "" "" (not val?))
(make-element (if val? value-color paren-color) '(" .")))))
(make-element (if val? value-color paren-color) '(" .")))
(+ (syntax-span a) 4)))
(list (syntax-source a)
(syntax-line a)
(- (syntax-column a) 2)
@ -327,7 +331,7 @@
(out (if (and (identifier? c)
color?
(quote-depth . <= . 0)
(not (or it? is-kw? is-var?)))
(not (or it? is-var?)))
(make-delayed-element
(lambda (renderer sec ht)
(let* ([vtag (register-scheme-definition (syntax-e c))]

View File

@ -214,7 +214,7 @@ This pruning behavior of @scheme[#:when] is more useful with
@scheme[for/list] than @scheme[for]. Whereas a plain @scheme[when]
form normally suffices with @scheme[for], a @scheme[when] expression
form in a @scheme[for/list] would cause the result list to contain
@void-const[]s instead of omitting list elements.
@|void-const|s instead of omitting list elements.
The @scheme[for*/list] is like @scheme[for*], nesting multiple
iterations:

View File

@ -189,7 +189,7 @@ simpler (just a procedure call).
We have ignored several other variants of the interation
form---including plain @scheme[for], which is used when the iteration
body is to be run only for its effect. For more complete information,
see @secref["iterations+comprehensions"].
see @secref["for"].
@;------------------------------------------------------------------------
@section{List Iteration from Scratch}

View File

@ -8,14 +8,14 @@
Some procedures or expression forms have no need for a result
value. For example, the @scheme[display] procedure is called only for
the side-effect of writing output. In such cases the reslt value is
normally a special constant that prints as @void-const[]. When the
result of an expression is simply @void-const[], the REPL does not
normally a special constant that prints as @|void-const|. When the
result of an expression is simply @|void-const|, the REPL does not
print anything.
The @scheme[void] procedure takes any number of arguments and returns
@void-const[]. (That is, the identifier @schemeidfont{void} is bound
to a procedure that returns @void-const[], instead of being bound
directly to @void-const[].)
@|void-const|. (That is, the identifier @schemeidfont{void} is bound
to a procedure that returns @|void-const|, instead of being bound
directly to @|void-const|.)
@examples[
(void)
@ -23,16 +23,16 @@ directly to @void-const[].)
(list (void))
]
A constant that prints as @schemefont{#<undefined>} is used as the
result of a reference to a local binding when the binding is not yet
A constant that prints as @undefined-const is used as the result of a
reference to a local binding when the binding is not yet
initialized. Such early references are not possible for bindings that
corerspond to procedure arguments, @scheme[let] bindings, or
@scheme[let*] bindings; early reference requires a recursive binding
context, such as @scheme[letrec] or local @scheme[define]s in a
procedure body. Also, early references to top-level and module
top-level bindings raise an exception, instead of producing
@schemefont{#<undefined>}. For these reasons,
@schemefont{#<undefined>} rarely appears.
@|undefined-const|. For these reasons, @undefined-const rarely
appears.
@def+int[
(define (strange)

View File

@ -1,7 +1,7 @@
#reader(lib "docreader.ss" "scribble")
@require["mz.ss"]
@title[#:style 'toc]{Built-In Datatypes}
@title[#:style 'toc]{Core Datatypes and Procedures}
Each of the built-in datatypes comes with a set of procedures for
manipulating members of the datatype.
@ -196,10 +196,10 @@ If the @scheme[lst]s are empty, then @scheme[#f] is returned.}
@; ----------------------------------------------------------------------
@section[#:tag "void"]{Void and Undefined}
@defproc[(void [v any/c] ...) void?]{Returns the constant @void-const[]. Each
@defproc[(void [v any/c] ...) void?]{Returns the constant @|void-const|. Each
@scheme[v] argument is ignored.}
@defproc[(void? [v any/c]) void?]{Returns @scheme[#t] if @scheme[v] is the
constant @void-const[], @scheme[#f] otherwise.}
constant @|void-const|, @scheme[#f] otherwise.}

View File

@ -0,0 +1,250 @@
#reader(lib "docreader.ss" "scribble")
@require["mz.ss"]
@title[#:tag "mz:derived-syntax"]{Derived Syntactic Forms}
@section{Iterations and Comprehensions: @scheme[for], @scheme[for/list], ...}
@defform[(for (for-clause ...) . body)]{
Iteratively evaluates @scheme[body]. The @scheme[for-clause]s
introduce bindings whose scope inculdes @scheme[body] and that
determine the number of times that @scheme[body] is evaluated.
In the simple case, each @scheme[for-clause] has the form
@specsubform[[id seq-expr]]{}
In this case, the @scheme[_seq-expr]s are evaluated left-to-right, and
each must produce a sequence value (see @secref["mz:sequences"]). The
@scheme[for] form iterates by drawing an element from each sequence;
if any sequence is empty, then the iteration stops, and @|void-const|
is the result of the @scheme[for] expression. Otherwise a location is
created for each @scheme[_id] to hold the corresponding element. The
@scheme[_id]s are then bound in the @scheme[body], which is evaluated,
and whose result(s) is(are) ignored. Iteration continues with the next
element in each sequence and with fresh locations for each
@scheme[_id]. Zero @scheme[for-clause]s is equivalent to a single
@scheme[for-clause] that binds an unreferenced @scheme[_id] to a
sequence containing one element. All of the @scheme[_id]s must be
distinct according to @scheme[bound-identifier=?].
If any @scheme[for-clause] has the form
@specsubform[(code:line #:when guard-expr)]{}
then only the preceding clauses (containing no @scheme[#:when])
determine iteration as above, and the @scheme[body] is effectively
wrapped as
@schemeblock[
(when guard-expr
(for (for-clause ...) . body))
]
using the remaining @scheme[for-clauses].
@examples[
(for ([i '(1 2 3)]
[j "abc"]
#:when (odd? i)
[k #2(#t #f)])
(display (list i j k)))
(for ()
(display "here"))
(for ([i '()])
(error "doesn't get here"))
]}
@defform[(for/list (for-clause ...) . body)]{ Iterates like
@scheme[for], but that the last expression of @scheme[body] must
produce a single value, and the result of the @scheme[for/list]
expression is a list of the results in order.
@examples[
(for/list ([i '(1 2 3)]
[j "abc"]
#:when (odd? i)
[k #2(#t #f)])
(list i j k))
(for/list () 'any)
(for/list ([i '()])
(error "doesn't get here"))
]}
@defform[(for/and (for-clause ...) . body)]{ Iterates like
@scheme[for], but when last expression of @scheme[body] produces
@scheme[#f], then iteration terminates, and the result of the
@scheme[for/and] expression is @scheme[#f]. If the @scheme[body]
is never evaluated, then the result of the @scheme[for/and]
expression is @scheme[#t]. Otherwise, the result is the (single)
result from the last evaluation of @scheme[body].
@examples[
(for/and ([i '(1 2 3 "x")])
(i . < . 3))
(for/and ([i '(1 2 3 4)])
i)
(for/and ([i '()])
(error "doesn't get here"))
]}
@defform[(for/or (for-clause ...) . body)]{ Iterates like
@scheme[for], but when last expression of @scheme[body] produces
a value other than @scheme[#f], then iteration terminates, and
the result of the @scheme[for/or] expression is the same
(single) value. If the @scheme[body] is never evaluated, then the
result of the @scheme[for/or] expression is
@scheme[#f]. Otherwise, the result is @scheme[#f].
@examples[
(for/or ([i '(1 2 3 "x")])
(i . < . 3))
(for/or ([i '(1 2 3 4)])
i)
(for/or ([i '()])
(error "doesn't get here"))
]}
@defform[(for/first (for-clause ...) . body)]{ Iterates like
@scheme[for], but after @scheme[body] is evaluated the first
time, then the iteration terminates, and the @scheme[for/first]
result is the (single) result of @scheme[body]. If the
@scheme[body] is never evaluated, then the result of the
@scheme[for/first] expression is @scheme[#f].
@examples[
(for/first ([i '(1 2 3 "x")]
#:when (even? i))
(number->string i))
(for/first ([i '()])
(error "doesn't get here"))
]}
@defform[(for/last (for-clause ...) . body)]{ Iterates like
@scheme[for], but the @scheme[for/last] result is the (single)
result of of the last evaluation of @scheme[body]. If the
@scheme[body] is never evaluated, then the result of the
@scheme[for/last] expression is @scheme[#f].
@examples[
(for/last ([i '(1 2 3 4 5)]
#:when (even? i))
(number->string i))
(for/last ([i '()])
(error "doesn't get here"))
]}
@defform[(for/fold ([accum-id init-expr] ...) (for-clause ...). body)]{
Iterates like @scheme[for]. Before iteration starts, the
@scheme[init-expr]s are evaluated to produce initial accumulator
values. At the start of each out iteration, a location is generated
for each @scheme[accum-id], and the correspinding current accumulator
value is placed into the location. The last expression in
@scheme[body] must produce as many values as @scheme[accum-id]s, and
those values become the current accumulator values. When iteration
terminates, the result of the @scheme[fold/for] expression is(are) the
accumulator value(s).
@examples[
(for/fold ([sum 0]
[rev-roots null])
([i '(1 2 3 4)])
(values (+ sum i) (cons (sqrt i) rev-roots)))
]}
@defform[(for* (for-clause ...) . body)]{
Like @scheme[for], but with an implicit @scheme[#:when #t] between
each pair of @scheme[for-clauses], so that all sequence iterations are
nested.
@examples[
(for* ([i '(1 2)]
[j "ab"])
(display (list i j)))
]}
@defform[(for*/list (for-clause ...) . body)]{
Like @scheme[for/list], but with the implicit nesting of @scheme[for*].
@examples[
(for*/list ([i '(1 2)]
[j "ab"])
(list i j))
]}
@defform[(for*/and (for-clause ...) . body)]{
Like @scheme[for/and], but with the implicit nesting of @scheme[for*].}
@defform[(for*/or (for-clause ...) . body)]{
Like @scheme[for/or], but with the implicit nesting of @scheme[for*].}
@defform[(for*/first (for-clause ...) . body)]{
Like @scheme[for/first], but with the implicit nesting of @scheme[for*].}
@defform[(for*/last (for-clause ...) . body)]{
Like @scheme[for/last], but with the implicit nesting of @scheme[for*].}
@defform[(for*/fold ([accum-id init-expr] ...) (for-clause ...) . body)]{
Like @scheme[for/fold], but with the implicit nesting of @scheme[for*].}
@defform[(for-values (for-values-clause ...) . body)]{ Like
@scheme[for], but each @scheme[for-values-clause] has one of the
following two forms:
@specsubform[[(id ...) seq-expr]]{ The sequence produced by
@scheme[_seq-expr] must return as many values for each iteration as
@scheme[id]s, and the values are placed in the locations generated
for the @scheme[id]s.}
@specsubform[(code:line #:when guard-expr)]{As in @scheme[for].}
@examples[
(for-values ([(i j) #hash(("a" . 1) ("b" . 20))])
(display (list i j)))
]}
@defform[(for/list-values (for-values-clause ...) . body)]{ Like
@scheme[for/list], but with multiple-value clauses like
@scheme[for-values].}
@defform[(for/and-values (for-values-clause ...) . body)]{ Like
@scheme[for-and], but with multiple-value clauses like
@scheme[for-values].}
@defform[(for/or-values (for-values-clause ...) . body)]{ Like
@scheme[for/or], but with multiple-value clauses like
@scheme[for-values].}
@defform[(for/first-values (for-values-clause ...) . body)]{ Like
@scheme[for/first], but with multiple-value clauses like
@scheme[for-values].}
@defform[(for/last-values (for-values-clause ...) . body)]{ Like
@scheme[for/last], but with multiple-value clauses like
@scheme[for-values].}
@defform[(for/fold-values ([id expr] ...) (for-values-clause ...) . body)]{ Like
@scheme[for/fold], but with multiple-value clauses like
@scheme[for-values].}
@defform[(for*-values (for-values-clause ...) . body)]{
Like @scheme[for-values], but with the implicit nesting of @scheme[for*].}
@defform[(for*/list-values (for-values-clause ...) . body)]{
Like @scheme[for/list-values], but with the implicit nesting of @scheme[for*].}
@defform[(for*/and-values (for-values-clause ...) . body)]{
Like @scheme[for/and-values], but with the implicit nesting of @scheme[for*].}
@defform[(for*/or-values (for-values-clause ...) . body)]{
Like @scheme[for/or-values], but with the implicit nesting of @scheme[for*].}
@defform[(for*/first-values (for-values-clause ...) . body)]{
Like @scheme[for/first-values], but with the implicit nesting of @scheme[for*].}
@defform[(for*/last-values (for-values-clause ...) . body)]{
Like @scheme[for/last-values], but with the implicit nesting of @scheme[for*].}
@defform[(for*/fold-values ([id expr] ...) (for-values-clause ...) . body)]{
Like @scheme[for/fold-values], but with the implicit nesting of @scheme[for*].}

View File

@ -177,7 +177,7 @@ right-hand expression must be reduced to a value.
[{}
(begin (code:hilite (define x 10)) (+ x 1))]
[{(define x 10)}
(code:hilite (begin #,(void-const) (+ x 1)))]
(code:hilite (begin #,void-const (+ x 1)))]
[{(define x 10)}
(+ (code:hilite x) 1)]
[{(define x 10)}
@ -197,7 +197,7 @@ existing top-level binding:
[{(define x 10)}
(begin (code:hilite (set! x 8)) x)]
[{(define x 8)}
(code:hilite (begin #,(void-const) x))]
(code:hilite (begin #,void-const x))]
[{(define x 8)}
(code:hilite x)]
[{(define x 8)}
@ -217,7 +217,7 @@ values, which are the results of expressions, and @defterm{objects},
which hold the data referenced by a value.
A few kinds of objects can serve directly as values, including
booleans, @void-const[], and small exact integers. More generally,
booleans, @|void-const|, and small exact integers. More generally,
however, a value is a reference to an object. For example, a value can
be a reference to a particular vector that currently holds the value
@scheme[10] in its first slot. If an object is modified, then the
@ -243,7 +243,7 @@ create objects, such as @scheme[vector], add to the set of objects:
(vector-ref y 0))]
[{(define <o1> #(10 20))}
{(define x <o1>)}
(code:hilite (begin #,(void-const)
(code:hilite (begin #,void-const
(define y x)
(vector-set! x 0 11)
(vector-ref y 0)))]
@ -260,7 +260,7 @@ create objects, such as @scheme[vector], add to the set of objects:
[{(define <o1> #(10 20))}
{(define x <o1>)
(define y <o1>)}
(code:hilite (begin #,(void-const)
(code:hilite (begin #,void-const
(vector-set! x 0 11)
(vector-ref y 0)))]
[{(define <o1> #(10 20))}
@ -276,7 +276,7 @@ create objects, such as @scheme[vector], add to the set of objects:
[{(define <o1> #(11 20))}
{(define x <o1>)
(define y <o1>)}
(code:hilite (begin #,(void-const)
(code:hilite (begin #,void-const
(vector-ref y 0)))]
[{(define <o1> #(11 20))}
{(define x <o1>)
@ -432,7 +432,7 @@ the variable is always replaced with a location by the time the
[{(define <p1> (lambda (x) (begin (set! x 3) x)))}
{(define f <p1>)
(define xloc 3)}
(code:hilite (begin #,(void-const) xloc))]
(code:hilite (begin #,void-const xloc))]
[{(define <p1> (lambda (x) (begin (set! x 3) x)))}
{(define f <p1>)
(define xloc 3)}

View File

@ -388,7 +388,7 @@ noted above). Two numbers are @scheme[equal?] when they are
@; ------------------------------------------------------------------------
@section{Trigonometric Functions}
@section{Trignometric Functions}
@defproc[(sin [z number?]) number?]{ Returns the sine of @scheme[z], where
@scheme[z] is in radians.

View File

@ -15,6 +15,7 @@ language.
@include-section["read.scrbl"]
@include-section["macros.scrbl"]
@include-section["syntax.scrbl"]
@include-section["derived.scrbl"]
@include-section["data.scrbl"]
@index-section["mzscheme-index"]

View File

@ -1,11 +1,23 @@
#reader(lib "docreader.ss" "scribble")
@require["mz.ss"]
@title[#:tag "mz:syntax"]{Core Syntactic Forms}
@title[#:tag "mz:syntax" #:style 'toc]{Core Syntactic Forms}
A syntactic form is described by a BNF-like notation that describes a
combination of (syntax-wrapped) pairs, symbols, and other data (not a
sequence of characters):
This section describes core syntax forms that apear in a fully
expanded expression, plus a few closely-related non-core forms.
@local-table-of-contents[]
@subsubsub*section{Notation}
Each syntactic form is described by a BNF-like notation that describes
a combination of (syntax-wrapped) pairs, symbols, and other data (not
a sequence of characters). These grammatical specifications are shown
as follows:
@specsubform[(#, @schemekeywordfont{some-form} id ...)]
Within such specifications,
@itemize{
@ -18,61 +30,86 @@ sequence of characters):
@item{@scheme[?] means zero instances or one instance
of the preceding datum.}
@item{Italic sequences of characters play the role of non-terminals. In
particular:
@item{italic meta-identifier play the role of non-terminals; in
particular,
@itemize{
@item{A sequence that ends in @scheme[_id] refers to a
@item{a meta-identifier that ends in @scheme[_id] stands for a
syntax-wrapped symbol.}
@item{A sequence that ends in @scheme[_keyword] refers to a
syntax-wrapped keyword.}
@item{a meta-identifier that ends in @scheme[_keyword] stands
for a syntax-wrapped keyword.}
@item{A sequence that end with @scheme[_expr] refers to a sub-form
that is expanded as an expression.}
}}
}
@item{a meta-identifier that ends with @scheme[_expr] stands
for a sub-form that is expanded as an expression.}
@item{a meta-identifier that ends with @scheme[_body] stands
for a non-empty syntax-wrapped list of sub-forms; the
list is expanded as internal-definition sequence
followed by at least one expression (see
@secref["intdef-body"] for details).}
}} }
@;------------------------------------------------------------------------
@section{Variable Reference}
@section{Variable References and @scheme[#%top]}
@defform/none[id]{
A reference to a module-level or local binding, when @scheme[id] is
Refers to a module-level or local binding, when @scheme[id] is
not bound as a transformer (see @secref["mz:expansion"]). At run-time,
the reference evaluates to the value in the location associated with
the binding.
When the expander encounters an @scheme[id] that is not bound by a
module or local binding, it converts the expression to @scheme[(#%top
. id)].}
module or local binding, it converts the expression to @scheme[(#,
@schemeidfont{#%top} . id)] giving @schemeidfont{#%top} the lexical
context of the @scheme[id]; typically, that context refers to
@scheme[#%top].
@examples[
(define x 10)
x
(let ([x 5]) x)
((lambda (x) x) 2)
]}
@defform[(#%top . id)]{
A reference to a top-level definition that could bind @scheme[id],
Refers to a top-level definition that could bind @scheme[id],
even if @scheme[id] has a local binding in its context. Such
references are disallowed anywhere within a @scheme[module] form.}
references are disallowed anywhere within a @scheme[module] form.
@examples[
(define x 12)
(let ([x 5]) (#%top . x))
]}
@;------------------------------------------------------------------------
@section{Procedure Application}
@section{Procedure Applications and @scheme[#%app]}
@defform/none[(proc-expr arg ...)]{
A procedure application, normally, when @scheme[proc-expr] is not an
Applies a procedure, normally, when @scheme[proc-expr] is not an
identifier that has a transformer binding (see
@secref["mz:expansion"]).
More precisely, the expander converts this form to @scheme[(#,
@schemeidfont{#%app} proc-expr arg ...)] using the lexical
context for @schemeidfont{#%app} that is associated with the original
form (i.e., the pair that combines @scheme[proc-expr] and its
@schemeidfont{#%app} proc-expr arg ...)], giving @schemeidfont{#%app}
the lexical context that is associated with the original form (i.e.,
the pair that combines @scheme[proc-expr] and its
arguments). Typically, the lexical context of the pair indicates the
procedure-application @scheme[#%app] that is described next.}
procedure-application @scheme[#%app] that is described next.
@examples[
(+ 1 2)
((lambda (x #:arg y) (list y x)) #:arg 2 1)
]}
@defform[(#%app proc-expr arg ...)]{
A procedure application. Each @scheme[arg] is one of the following:
Applies a procedure. Each @scheme[arg] is one of the following:
@specsubform[arg-expr]{The resulting value is a non-keyword
argument.}
@ -85,7 +122,7 @@ The @scheme[proc-expr] and @scheme[_arg-expr]s are evaluated in order,
left to right. If the result of @scheme[proc-expr] is a procedure that
accepts as many arguments as non-@scheme[_keyword]
@scheme[_arg-expr]s, if it accepts arguments for all of the
e@scheme[_keyword]s in the application, and if all required
@scheme[_keyword]s in the application, and if all required
keyword-based arguments are represented among the @scheme[_keyword]s
in the application, then the procedure is called with the values of
the @scheme[arg-expr]s. Otherwise, the @exnraise[exn:fail:contract].
@ -96,20 +133,26 @@ expression is(are) the result(s) of the procedure.
The relative order of @scheme[_keyword]-based arguments matters only
for the order of @scheme[_arg-expr] evaluations; the arguments are
regonized by the applied procedure based on the @scheme[_keyword], and
not their positions. The other @scheme[_arg-expr] values, in contrast,
are recognized by the applied procedure according to their order in
the application form.}
associated with argument variables in the applied procedure based on
the @scheme[_keyword]s, and not their positions. The other
@scheme[_arg-expr] values, in contrast, are associated with variables
according to their order in the application form.
@examples[
(#%app + 1 2)
(#%app (lambda (x #:arg y) (list y x)) #:arg 2 1)
(#%app cons)
]}
@;------------------------------------------------------------------------
@section{Procedure Expression: @scheme[lambda] and @scheme[case-lambda]}
@section{Procedure Expressions: @scheme[lambda] and @scheme[case-lambda]}
@defform[(lambda formals* body-expr ...+)]{
@defform[(lambda formals* . body)]{
An expression that procedures a procedure. The @scheme[formals*]
determines the number of arguments that the procedure accepts. It is
either a simple @scheme[_formals], or one of the extended forms.
Procedures a procedure. The @scheme[formals*] determines the number of
arguments that the procedure accepts. It is either a simple
@scheme[_formals], or one of the extended forms.
A simple @scheme[_formals] has one of the following three forms:
@ -128,11 +171,11 @@ A simple @scheme[_formals] has one of the following three forms:
arguments. All arguments are placed into a list that is
associated with @scheme[rest-id].}
In addition to the form of a @scheme[_formals], a @scheme[formals*]
can be a sequence of @scheme[_formal*]s optionally ending with a
Besides the three @scheme[_formals] forms, a @scheme[formals*] can be
a sequence of @scheme[_formal-arg]s optionally ending with a
@scheme[rest-id]:
@specsubform[(formal* ...)]{ Each @scheme[formal*] has the following
@specsubform[(formal-arg ...)]{ Each @scheme[formal-arg] has the following
four forms:
@specsubform[id]{Adds one to both the minimum and maximum
@ -145,7 +188,7 @@ can be a sequence of @scheme[_formal*]s optionally ending with a
@scheme[id] is associated with an actual argument by position,
and if no such argument is provided, the @scheme[default-expr]
is evaluated to produce a value associated with @scheme[id].
No @scheme[formal*] with a @scheme[default-expr] can appear
No @scheme[formal-arg] with a @scheme[default-expr] can appear
before an @scheme[id] without a @scheme[default-expr] and
without a @scheme[keyword].}
@ -161,25 +204,26 @@ can be a sequence of @scheme[_formal*]s optionally ending with a
otherwise, the @scheme[default-expr] is evaluated to obtain a
value to associate with @scheme[id].}
The position of a @scheme[_keyword] @scheme[formal*] in
The position of a @scheme[_keyword] @scheme[formal-arg] in
@scheme[formals*] does not matter, but each specified
@scheme[_keyword] must be distinct.}
@specsubform[(formal* ...+ . rest-id)]{ Like the previous case, but
@specsubform[(formal-arg ...+ . rest-id)]{ Like the previous case, but
the procedure accepts any number of non-keyword arguments
beyond its minimum number of arguments. When more arguments are
provided than non-@scheme[_keyword] arguments among the @scheme[formal*]s,
the extra arguments are placed into a list that is associated to
@scheme[rest-id].}
beyond its minimum number of arguments. When more arguments are
provided than non-@scheme[_keyword] arguments among the
@scheme[formal-arg]s, the extra arguments are placed into a
list that is associated to @scheme[rest-id].}
The @scheme[formals*] identifiers are bound in the
@scheme[body-expr]s. When the procedure is applied, a new location is
created for each identifier, and the location is filled with the
associated argument value.
The @scheme[formals*] identifiers are bound in the @scheme[body]. (See
@secref["intdef-body"] for information on @scheme[body] forms.) When
the procedure is applied, a new location is created for each
identifier, and the location is filled with the associated argument
value.
If any identifier appears in @scheme[body-expr]s that is not one of
the identifiers in @scheme[formals*], then it refers to the same
location that it would if it appears in place of the @scheme[lambda]
If any identifier appears in @scheme[body] that is not one of the
identifiers in @scheme[formals*], then it refers to the same location
that it would if it appeared in place of the @scheme[lambda]
expression. (In other words, variable reference is lexically scoped.)
When multiple identifiers appear in a @scheme[formals*], they must be
@ -189,14 +233,25 @@ If the procedure procedure by @scheme[lambda] is applied to fewer or
more arguments than it accepts, the @exnraise[exn:fail:contract]. If
@scheme[formals*] includes @scheme[keyword]s and an application
includes too few arguments before the keyword section, the same
keyword in multiple odd positions of the keyword section, or a keyword
that is not among the @scheme[formals*] @scheme[keyword]s in an odd
position of the keyword section, then the
@exnraise[exn:fail:contract].}
keyword in multiple positions, or a keyword that is not among the
@scheme[formals*] @scheme[_keyword]s, then the
@exnraise[exn:fail:contract].
@defform[(case-lambda [formals body-expr ...+] ...)]{
The last expression in @scheme[body] is in tail position with respect
to the procedure body.
An expression that procedure. Each @scheme[[forms body-expr ...+]]
@examples[
((lambda (x) x) 10)
((lambda (x y) (list y x)) 1 2)
((lambda (x [y 5]) (list y x)) 1 2)
(let ([f (lambda (x #:arg y) (list y x))])
(list (f 1 #:arg 2)
(f #:arg 2 1)))
]}
@defform[(case-lambda [formals . body] ...)]{
Produces a procedure. Each @scheme[[forms body]]
clause is analogous to a single @scheme[lambda] procedure; applying
the @scheme[case-lambda]-generated procedure is the same as applying a
procedure that corresponds to one of the clauses---the first procedure
@ -207,4 +262,126 @@ procedure accepts the given number of arguments, the
Note that a @scheme[case-lambda] clause supports only
@scheme[formals], not the more general @scheme[_formals*] of
@scheme[lambda]. That is, @scheme[case-lambda] does not directly
support keyword and optional arguments for an inidvidual clause.}
support keyword and optional arguments.
@examples[
(let ([f (case-lambda
[() 10]
[(x) x]
[(x y) (list y x)]
[r r])])
(list (f)
(f 1)
(f 1 2)
(f 1 2 3)))
]}
@;------------------------------------------------------------------------
@section{Local Binding: @scheme[let], @scheme[let*], and @scheme[letrec]}
@defform*[[(let ([id val-expr] ...) . body)
(let proc-id ([id init-expr] ...) . body)]]{
The first form evaluates the @scheme[val-expr]s left-to-right, creates
a new location for each @scheme[id], and places the values into the
locations. It then evaluates the @scheme[body], in which the
@scheme[id]s are bound. (See @secref["intdef-body"] for information
on @scheme[body] forms.) The last expression in @scheme[body] is in
tail position with respect to the @scheme[let] form. The @scheme[id]s
must be distinct according to @scheme[bound-identifier=?].
@examples[
(let ([x 5]) x)
(let ([x 5])
(let ([x 2]
[y x])
(list y x)))
]
The second form evaluates the @scheme[init-expr]s; the resulting
values become arguments in an application of a procedure
@scheme[(lambda (id ...) . body)], where @scheme[proc-id] is bound
within @scheme[body] to the procedure itself.}
@examples[
(let fac ([n 10])
(if (zero? n)
1
(* n (fac (sub1 n)))))
]
@defform[(let* ([id val-expr] ...) . body)]{
Similar to @scheme[let], but evaluates the @scheme[val-expr]s one by
one, creating a location for each @scheme[id] as soon as the value is
available, and binding @scheme[id] in the remaining @scheme[val-expr]s
as well as the @scheme[body]. The @scheme[id]s need not be distinct.
@examples[
(let ([x 1]
[y (+ x 1)])
(list y x))
]}
@defform[(letrec ([id val-expr] ...) . body)]{
Similar to @scheme[let], but the locations for all @scheme[id]s are
created first and filled with @|undefined-const|, and all
@scheme[id]s are bound in all @scheme[val-expr]s as well as
@scheme[body]. The @scheme[id]s must be distinct according to
@scheme[bound-identifier=?].
@examples[
(letrec ([is-even? (lambda (n)
(or (zero? n)
(is-odd? (sub1 n))))]
[is-odd? (lambda (n)
(or (= n 1)
(is-even? (sub1 n))))])
(is-odd? 11))
]}
@defform[(let-values ([(id ...) val-expr] ...) . body)]{ Like
@scheme[let], except that each @scheme[val-expr] must produce as many
values as corresponding @scheme[id]s. A separate location is created
for each @scheme[id], all of which are bound in the @scheme[body].
@examples[
(let-values ([(x y) (quotient/remainder 10 3)])
(list y x))
]}
@defform[(let*-values ([(id ...) val-expr] ...) . body)]{ Like
@scheme[let*], except that each @scheme[val-expr] must produce as many
values as corresponding @scheme[id]s. A separate location is created
for each @scheme[id], all of which are bound in the later
@scheme[val-expr]s and in the @scheme[body].
@examples[
(let*-values ([(x y) (quotient/remainder 10 3)]
[(z) (list y x)])
z)
]}
@defform[(letrec-values ([(id ...) val-expr] ...) . body)]{ Like
@scheme[letrec], except that each @scheme[val-expr] must produce as
many values as corresponding @scheme[id]s. A separate location is
created for each @scheme[id], all of which are initialized to
@|undefined-const| and bound in all @scheme[val-expr]s
and in the @scheme[body].
@examples[
(letrec-values ([(is-even? is-odd?)
(values
(lambda (n)
(or (zero? n)
(is-odd? (sub1 n))))
(lambda (n)
(or (= n 1)
(is-even? (sub1 n)))))])
(is-odd? 11))
]}
@;------------------------------------------------------------------------
@section{Sequencing: @scheme[begin]}

View File

@ -307,9 +307,9 @@ for the index entry.}
@defthing[PLaneT string?]{@scheme["PLaneT"] (to help make sure you get
the letters in the right case).}
@defproc[(void-const) any/c]{Returns @scheme["void"], as opposed to
@scheme[(scheme void)]---but we may eventually find a clearer way to
refer to @void-const in prose.}
@defthing[void-const element?]{Returns an element for @|void-const|.}
@defthing[undefined-const element?]{Returns an element for @|undefined-const|.}
@defproc[(centerline [pre-flow any/c] ...0) table?]{Produces a
centered table with the @scheme[pre-flow] parsed by