In an application expression, the procedure expression and the
argument expressions are always evaluated left-to-right. Similarly,
expressions for let and letrec bindings are
evaluated in sequence from left to right.
MzScheme supports the R5RSvalues and
call-with-values procedure, and also provides binding forms for
multiple-value expressions, discussed in section 2.8.
Multiple return values are legal in MzScheme whenever the return value
of an expression is ignored. For example, all but the last
expression in a begin form can legally return multiple
values in any context. If a built-in procedure takes a procedure
argument, and the built-in procedure does not inspect the result of
the supplied procedure, then the supplied procedure can return
multiple values. For example, the procedure supplied to
for-each can return any number of values, but the procedure
supplied to map must return a single value.
When the number of values returned by an expression does not match the
number of values expected by the expression's context, the
exn:application:arity exception is raised (at run time).
The when and unless forms conditionally
evaluate a single body of expressions:
(whentest-exprexpr···1) evaluates the
expr body expressions only when test-expr returns a
true value.
(unlesstest-exprexpr···1) evaluates the
expr body expressions only when test-expr returns
#f.
The result of a when or unless expression is the result of
the last body expression if the body is evaluated, or void (see
section 3.1) if the body is not evaluated.
In an and or or expression, the last test
expression can return multiple values (see section 2.2). If the last
expression is evaluated and it returns multiple values, then the
result of the entire and or or expression is the multiple
values. Other sub-expressions in an and or or
expression must return a single value.
The quote form never allocates, so that the result of multiple
evaluations of a single quote expression are always eq?.
Nevertheless, a quoted cons cell, vector, or list is mutable;
mutations to the result of a quote application are visible to
future evaluations of the quote expression.
The quasiquote form allocates only as many fresh cons cells,
vectors, and boxes as are needed without analyzing unquote
and unquote-splicing expressions. For example, in
`(,123)
a single reader-allocated tail '(23) is used for every
evaluation of the quasiquote expression.
The standard Scheme quasiquote has been extended so that
unquote and unquote-splicing work within immediate boxes:
`#&(,(-21) ,@(list23)) ; => #&(123)
See section 14.3 for more information about immediate boxes.
MzScheme defines the unquote and
unquote-splicing identifiers as top-level syntactic forms
that always report a syntax error. The quasiquote form
recognizes normal unquote and unquote-splicing
uses via module-identifier=?. (See section 12.3.1 for more
information on identifier comparisons.)
Local variables are bound with standard Scheme's let,
let*, and letrec. MzScheme's
letrec form guarantees sequential left-to-right
evaluation of the binding expressions.
Multiple values are bound to multiple local variables at once with
let-values, let*-values, and
letrec-values. The syntax for let-values is:
As in define-values, the number of values returned by each
expr must match the number of variables declared in the
corresponding clause. Each expr remains outside of the scope of
all variables bound by the let-values expression.
The syntax for let*-values and letrec-values is the same
as for let-values, and the binding semantics for each form
corresponds to the single-value binding form:
In a let*-values expression, the scope of the variables
of each clause includes all of the remaining binding clauses. The
clause expressions are evaluated and bound to variables sequentially.
In a letrec-values expression, the scope of the variables
of each clause includes all of the binding clauses. The clause
expressions are evaluated and bound to variables sequentially.
When a letrec or letrec-values expression is evaluated,
each variable binding is initially assigned the special undefined
value (see section 3.1); the undefined value is replaced
after the corresponding expression is evaluated.
The standard set! form assigns a value to a
single global, local, or module variable. Multiple variables can be
assigned at once using set!-values:
(set!-values (variable···) expr)
The number of values returned by expr must match the number of
variables provided.
The variables, which must be distinct, can be any mixture of
global, local, and module variables. Assignments are performed
sequentially from the first variable to the last. If an error
occurs in one of the assignments (perhaps because a global variable
is not yet bound), then the assignments for the preceding
variables will have already completed, but assignments for the
remaining variables will never complete.
The syntax for a fluid-let expression is the same as for
let:
(fluid-let ((variableexpr) ···) body-expr···1)
Each variable must be either a local variable or a global or
module variable that is bound before the fluid-let expression
is evaluated. Before the body-exprs are evaluated, the
bindings for the variables are set! to the values of the
corresponding exprs. Once the body-exprs have been
evaluated, the values of the variables are restored. The value of the
entire fluid-let expression is the value of the last
body-expr.
All binding forms are syntax-expanded into define-values,
let-values, letrec-values, define-syntaxes,
letrec-syntaxes+values, and fluid-let-syntax
expressions. The set!-values form is expanded to
let-values with set!. See section 12.6.1 for
more information.
All define-values expressions that are inside only
begin expressions are treated as top-level
definitions. Body define-values expressions in a
module expression are handled specially as described in
section 5.1. Any other define-values expression is
either an internal definition or syntactically illegal.
The same is true of define-syntaxes expressions.
Internal definitions can appear at the start of a sequence of
expressions, such as the start of a lambda,
case-lambda, or let body. At least one
non-definition expression must follow a sequence of internal
definitions. The first expression in a begin0 expression
cannot be an internal definition; for the purposes of internal
definitions, the second expression is the start of the sequence.
When a begin expression appears within a sequence, its
content is inlined into the sequence (recursively, if the
begin expression contains other begin
expressions). Like top-level begin expressions (and unlike
other begin expressions), a begin expression within
an internal definition sequence can be empty.
An internal define-values or define-syntaxes
expression is transformed, along with the expressions following it,
into a letrec-syntaxes+values expression: the variables
bound by the internal definitions become the binding variables of the
new letrec-syntaxes+values expression, and the expressions
that follow the definitions become the body of the new
letrec-syntaxes+values expression.
Multiple adjacent definitions are collected into a single
letrec-syntaxes+values transformation, so that the
definitions can be mutually recursive, but the definitions
expressions must be adjacent. A non-definition marks the start of a
sequence of expressions to be moved into the body of the newly
created letrec-syntaxes+values form.
Internal definitions are detected after a partial syntax expansion
that exposes begin, define-values, and
define-syntaxes forms without expanding the definition
body. Therefore, an internal definition can shadow a syntactic form
in the value part of other embedded definitions. However, an embedded
definition cannot alter the decision of whether another expression is
also an embedded definition in the same
letrec-syntaxes+values transformation, because the
definitions are collected through partial expansion before any new
scope is created.
The case-lambda form creates a procedure that dispatches
to a particular body of expressions based on the number of arguments
that the procedure receives. The case-lambda form provides a
mechanism for creating variable-arity procedures with more control
and efficiency than using a lambda ``rest argument,'' such
as the x in (lambda (a . x) expr···1).
A case-lambda expression has the form:
(case-lambda
(formalsexpr···1)
···)
formals is one of
variable
(variable···)
(variable··· . variable)
Each (formalsexpr···1) clause of a case-lambda
expression is analogous to a lambda expression of the form
(lambdaformalsexpr···1). The scope of the
variables in each clause's formals includes only the same
clause's exprs. The formals variables are bound to actual
arguments in an application in the same way that lambda
variables are bound in an application.
When a case-lambda procedure is invoked, one clause is selected
and its exprs are evaluated for the application; the result of
the last expr in the clause is the result of the
application. The clause that is selected for an application is the
first one with a formals specification that can accommodate the
number of arguments in the application.1
The result of a case-lambda expression is a procedure, just
like the result of a lambda expression. Thus, the
procedure? predicate returns #t when applied to
the result of a case-lambda expression.