#

Basic Syntax Extensions

## 2.1 Evaluation Order

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.

## 2.2 Multiple Return Values

MzScheme supports the *R5RS*

and
`values`

procedure, and also provides binding forms for
multiple-value expressions, discussed in section 2.8.`call-with-values`

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

can return any number of values, but the procedure
supplied to `for-each`

must return a single value.`map`

When the number of values returned by an expression does not match the
number of values expected by the expression's context, the
`exn:fail:contract:arity`

exception is raised (at run time).

Examples:

(- (`values`

1)) ; =>`-1`

(- (`values`

1 2)) ; => error: returned 2 values to single-value context (- (`values`

)) ; => error: returned 0 values to single-value context (`call-with-values`

(lambda () (`values`

1 2)) (lambda (x y) y)) ; =>`2`

(`call-with-values`

(lambda () (`values`

1 2)) (lambda z z)) ; => (1 2) (`call-with-values`

(lambda () (let/cc k (k 3 4))) (lambda (x y) y)) ; =>`4`

(`call-with-values`

(lambda () (`values`

'hello 1 2 3 4)) (lambda (s . l) (`format`

"~s = ~s" s l))) ; =>`"hello = (1 2 3 4)"`

## 2.3 Cond and Case

The `else`

and `=>`

identifiers in a `cond`

or
`case`

statement are handled specially only when they are not
lexically bound or module-bound:

(cond [1 =>`add1`

]) ; =>`2`

(let ([=> 5]) (cond [1 =>`add1`

])) ; =>`#<primitive:add1>`

## 2.4 When and Unless

The `when`

and `unless`

forms conditionally
evaluate a single body of expressions:

`(when test-expr expr`

evaluates the`···`^{1})`expr`

body expressions only when`test-expr`

returns a true value.`(unless test-expr expr`

evaluates the`···`^{1})`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.

## 2.5 And and Or

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.

## 2.6 Sequences

The `begin0`

form is like `begin`

, but the value
of the first expression in the form is returned instead of the value
of the last expression:

(let ([x 4]) (begin0 x (set! x 9) (`display`

x))) ; =>`s`

`display`

`9`

then returns`4`

The first sub-expression in a `begin0`

expression is in tail
position if and only if it is the only sub-expression.

## 2.7 Quote and Quasiquote

The `quote`

form never allocates, so that the result of multiple
evaluations of a single `quote`

expression are always

.
Nevertheless, a quoted cons cell, vector, or list is mutable;
mutations to the result of a `eq?`

`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

`(,1 2 3)

a single reader-allocated tail `'(2 3)`

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:

`#&(,(- 2 1) ,@(`list`

2 3)) ; =>`#&(1 2 3)`

See section 11.2.4 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

. (See section 12.3.1 for more
information on identifier comparisons.)`module-identifier=?`

## 2.8 Binding Forms

### 2.8.1 Definitions

A procedure definition

(define variable (lambda formals expr···^{1}))

can be abbreviated

(define (variable . formals) expr···^{1})

In addition to this standard Scheme abbreviation, MzScheme supports an MIT-style generalization, so that a definition

(define header (lambda formals expr···^{1}))

can be abbreviated

(define (header . formals) expr···^{1}))

even if `header`

is itself a parenthesized procedure
abbreviation. The general syntax of `define`

is as
follows:

(define variable expr) (define (header . formals) expr···^{1}) header is one of variable (header . formals) formals is one of variable (variable···) (variable variable···. variable)

Multiple values can be bound to multiple variables at once using
`define-values`

:

(define-values (variable···) expr)

The number of values returned by `expr`

must match the number of
`variable`

s provided, and the `variable`

s must be distinct.
No procedure-definition abbreviation is available for
`define-values`

.

Examples:

(define x 1) x ; =>`1`

(define (f x) (+ x 1)) (f 2) ; =>`3`

(define (((g x) y z) . w) (`list`

x y z w)) (let ([h ((g 1) 2 3)]) (`list`

(h 4 5) (h 6))) ; =>`'((1 2 3 (4 5)) (1 2 3 (6)))`

(define-values (x) 2) x ; =>`2`

(define-values (x y) (`values`

3 4)) x ; =>`3`

y ; =>`4`

(define-values (x y) (`values`

5 (`add1`

x))) y ; =>`4`

(define-values () (`values`

)) ; same as`(`

(define x (`void`

)`values`

7 8)) ; => error: 2 values for 1-value context (define-values (x y) 7) ; => error: 1 value for 2-value context (define-values () 7) ; => error: 1 value for 0-value context

### 2.8.2 Local Bindings

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. (The `letrec`

bound in
the result of `(scheme-report-environment `

, however, is
defined exactly as in `5`

)*R5RS*.)

Multiple values are bound to multiple local variables at once with
`let-values`

, `let*-values`

, and
`letrec-values`

. The syntax for `let-values`

is:

(let-values (((variable···) expr)···) body-expr···^{1})

As in `define-values`

, the number of values returned by each
`expr`

must match the number of `variable`

s 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.

Examples:

(define x 0) (let ([x 5] [y x]) y) ; =>`0`

(let* ([x 5] [y x]) y) ; =>`5`

(letrec ([x 5] [y x]) y) ; =>`5`

(letrec ([x y] [y 5]) x) ; => undefined (let-values ([(x) 5] [(y) x]) y) ; =>`0`

(let-values ([(x y) (`values`

5 x)]) y) ; =>`0`

(let*-values ([(x) 5] [(y) x]) y) ; =>`5`

(let*-values ([(x y) (`values`

5 x)]) y) ; =>`0`

(letrec-values ([(x) 5] [(y) x]) y) ; =>`5`

(letrec-values ([(x y) (`values`

5 x)]) y) ; => undefined (letrec-values ([(odd even) (`values`

(lambda (n) (if (`zero?`

n) #f (even (`sub1`

n)))) (lambda (n) (if (`zero?`

n) #t (odd (`sub1`

n)))))]) (odd 17)) ; =>`#t`

### 2.8.3 Assignments

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
`variable`

s provided.

The `variable`

s, 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
`variable`

s will have already completed, but assignments for the
remaining `variable`

s will never complete.

### 2.8.4 Fluid-Let

The syntax for a `fluid-let`

expression is the same as for
`let`

:

(fluid-let ((variable expr)···) 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-expr`

s are evaluated, the
bindings for the `variable`

s are `set!`

to the values of the
corresponding `expr`

s. Once the `body-expr`

s 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`

.

### 2.8.5 Syntax Expansion and Internal Definitions

All binding forms are syntax-expanded into `define-values`

,
`let-values`

, `letrec-values`

,
`define-syntaxes`

, and `letrec-syntaxes+values`

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 identifiers
bound by the internal definitions become the binding identifiers 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 stops at core forms, and thus
exposes `begin`

, `define-values`

,
and `define-syntaxes`

. Forms are expanded left to right, and
whenever a definition is discovered, a binding is introduced
immediately for further expansion, so a definition can shadow
variables when later forms are expanded. Furthermore, when
a `define-syntaxes`

form is discovered, the right-hand side is
immediately evaluated, and the result is bound as syntax to the
corresponding identifier(s); thus, a locally defined macro can be
used to generate later definitions in the same internal-definition
context.

## 2.9 Case-Lambda

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 (formals expr···^{1})···) formals is one of variable (variable···) (variable···. variable)

Each `(formals expr `

clause of a `···`^{1})`case-lambda`

expression is analogous to a `lambda`

expression of the form
`(lambda formals expr `

. The scope of the
`···`^{1})`variable`

s in each clause's `formals`

includes only the same
clause's `expr`

s. 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 `expr`

s 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.^{3}

Examples:

(define f (case-lambda [(x) x] [(x y) (+ x y)] [(a . any) a])) (f 1) ; =>`1`

(f 1 2) ; =>`3`

(f 4 5 6 7) ; =>`4`

(f) ; => raises`exn:fail:contract:arity`

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.

## 2.10 Procedure Application

The ``empty application'' form `()`

expands to the quoted empty
list `'()`

.

## 2.11 Variable Reference

The `#%variable-reference`

form returns a value
representing the address of a top-level or module variable:

(#%variable-reference variable) (#%variable-reference (#%top . variable))

In the non-`#%top`

form, a syntax error is reported
if `variable`

is not bound to a top-level or module variable.

The result of a `#%variable-reference`

expression is opaque, with no
useful operation in MzScheme. See *Inside PLT MzScheme* for
information on its use in low-level extensions to MzScheme.

^{3} It is possible that
a clause in a `case-lambda`

expression can never be evaluated
because a preceding clause always matches the arguments.