racket/collects/scribblings/reference/syntax.scrbl
2007-06-04 06:34:16 +00:00

211 lines
8.8 KiB
Racket

#reader(lib "docreader.ss" "scribble")
@require["mz.ss"]
@title[#:tag "mz:syntax"]{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):
@itemize{
@item{@scheme[...] indicates zero or more
repetitions of the preceding datum.}
@item{@scheme[...+] indicates one or
more repetitions of the preceding datum.}
@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:
@itemize{
@item{A sequence that ends in @scheme[_id] refers to a
syntax-wrapped symbol.}
@item{A sequence that ends in @scheme[_keyword] refers to a
syntax-wrapped keyword.}
@item{A sequence that end with @scheme[_expr] refers to a sub-form
that is expanded as an expression.}
}}
}
@;------------------------------------------------------------------------
@section{Variable Reference}
@defform/none[id]{
A reference 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)].}
@defform[(#%top . id)]{
A reference 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.}
@;------------------------------------------------------------------------
@section{Procedure Application}
@defform/none[(proc-expr arg ...)]{
A procedure application, 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
arguments). Typically, the lexical context of the pair indicates the
procedure-application @scheme[#%app] that is described next.}
@defform[(#%app proc-expr arg ...)]{
A procedure application. Each @scheme[arg] is one of the following:
@specsubform[arg-expr]{The resulting value is a non-keyword
argument.}
@specsubform[(code:line keyword arg-expr)]{The resulting value is a
keyword argument using @scheme[keyword]. Each
@scheme[keyword] in the application must be distinct.}
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
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].
The continuation of the procedure call is the same as the continuation
of the application expression, so the result(s) of the application
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.}
@;------------------------------------------------------------------------
@section{Procedure Expression: @scheme[lambda] and @scheme[case-lambda]}
@defform[(lambda formals* body-expr ...+)]{
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.
A simple @scheme[_formals] has one of the following three forms:
@specsubform[(id ... )]{ The procedure accepts as many non-keyword
argument values as the number of @scheme[id]s. Each @scheme[id]
is associated with an argument value by position.}
@specsubform[(id ...+ . rest-id)]{ The procedure accepts any number of
non-keyword arguments greater or equal to the number of
@scheme[id]s. When the procedure is applied, the @scheme[id]s
are associated with argument values by position, and all
leftover arguments are placed into a list that is associated to
@scheme[rest-id].}
@specsubform[rest-id]{ The procedure accepts any number of non-keyword
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
@scheme[rest-id]:
@specsubform[(formal* ...)]{ Each @scheme[formal*] has the following
four forms:
@specsubform[id]{Adds one to both the minimum and maximum
number of non-keyword arguments accepted by the procedure. The
@scheme[id] is associated with an actual argument by
position.}
@specsubform[[id default-expr]]{Adds one to the maximum number
of non-keyword arguments accepted by the procedure. The
@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
before an @scheme[id] without a @scheme[default-expr] and
without a @scheme[keyword].}
@specsubform[(code:line keyword id)]{The procedure requires a
keyword-based argument using @scheme[keyword]. The @scheme[id]
is associated with a keyword-based actual argument using
@scheme[keyword].}
@specsubform[(code:line keyword [id default-expr])]{The
procedure accepts a keyword-based using @scheme[keyword]. The
@scheme[id] is associated with a keyword-based actual argument
using @scheme[keyword], if supplied in an application;
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
@scheme[formals*] does not matter, but each specified
@scheme[_keyword] must be distinct.}
@specsubform[(formal* ...+ . 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].}
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.
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]
expression. (In other words, variable reference is lexically scoped.)
When multiple identifiers appear in a @scheme[formals*], they must be
distinct according to @scheme[bound-identifier=?].
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].}
@defform[(case-lambda [formals body-expr ...+] ...)]{
An expression that procedure. Each @scheme[[forms body-expr ...+]]
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
that accepts the given number of arguments. If no corresponding
procedure accepts the given number of arguments, the
@exnraise[exn:fail:contract].
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.}