[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

# 2. Special Forms

A special form is an expression that follows special evaluation rules. This chapter describes the basic Scheme special forms.

> 2.1 Lambda Expressions |  |
> 2.2 Lexical Binding |  |
> 2.3 Dynamic Binding |  |
> 2.4 Definitions |  |
> 2.5 Assignments |  |
> 2.6 Quoting |  |
> 2.7 Conditionals |  |
> 2.8 Sequencing |  |
> 2.9 Iteration |  |
> 2.10 Structure Definitions |  |
> 2.11 Macros |  |

[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

## 2.1 Lambda Expressions

special form: lambda formals expression expression ...
  A `lambda` expression evaluates to a procedure. The environment in effect when the `lambda` expression is evaluated is remembered as part of the procedure; it is called the closing environment. When the procedure is later called with some arguments, the closing environment is extended by binding the variables in the formal parameter list to fresh locations, and the locations are filled with the arguments according to rules about to be given. The new environment created by this process is referred to as the invocation environment.

  Once the invocation environment has been constructed, the expressions in the body of the `lambda` expression are evaluated sequentially in it. This means that the region of the variables bound by the `lambda` expression is all of the expressions in the body. The result of evaluating the last expression in the body is returned as the result of the procedure call.

  Formals, the formal parameter list, is often referred to as a lambda list.

  The process of matching up formal parameters with arguments is somewhat involved. There are three types of parameters, and the matching treats each in sequence:

  Required
    All of the required parameters are matched against the arguments first. If there are fewer arguments than required parameters, an error of type `condition-type:wrong-number-of-arguments` is signalled; this error is also signalled if there are more arguments than required parameters and there are no further parameters.

  Optional
    Once the required parameters have all been matched, the optional parameters are matched against the remaining arguments. If there are fewer arguments than optional parameters, the unmatched parameters are bound to special objects called default objects. If there are more arguments than optional parameters, and there are no further parameters, an error of type `condition-type:wrong-number-of-arguments` is signalled.

    The predicate `default-object?`, which is true only of default objects, can be used to determine which optional parameters were supplied, and which were defaulted.

  Rest
    Finally, if there is a rest parameter (there can only be one), any remaining arguments are made into a list, and the list is bound to the rest parameter. (If there are no remaining arguments, the rest parameter is bound to the empty list.)

    In Scheme, unlike some other Lisp implementations, the list to which a rest parameter is bound is always freshly allocated. It has infinite extent and may be modified without affecting the procedure's caller.

  Specially recognized keywords divide the formals parameters into these three classes. The keywords used here are ``#!optional`', ``.`', and ``#!rest`'. Note that only ``.`' is defined by standard Scheme -- the other keywords are MIT Scheme extensions. ``#!rest`' has the same meaning as ``.`' in formals.

  The use of these keywords is best explained by means of examples. The following are typical lambda lists, followed by descriptions of which parameters are required, optional, and rest. We will use ``#!rest`' in these examples, but anywhere it appears ``.`' could be used instead.

  `(a b c)`
    `a`, `b`, and `c` are all required. The procedure must be passed exactly three arguments.

  `(a b #!optional c)`
    `a` and `b` are required, `c` is optional. The procedure may be passed either two or three arguments.

  `(#!optional a b c)`
    `a`, `b`, and `c` are all optional. The procedure may be passed any number of arguments between zero and three, inclusive.

  `a`
  `(#!rest a)`
    These two examples are equivalent. `a` is a rest parameter. The procedure may be passed any number of arguments. Note: this is the only case in which ``.`' cannot be used in place of ``#!rest`'.

  `(a b #!optional c d #!rest e)`
    `a` and `b` are required, `c` and `d` are optional, and `e` is rest. The procedure may be passed two or more arguments.

  Some examples of `lambda` expressions:

      (lambda (x) (+ x x))            =>  #[compound-procedure 53]

      ((lambda (x) (+ x x)) 4)                =>  8

      (define reverse-subtract
        (lambda (x y)
          (- y x)))
      (reverse-subtract 7 10)                 =>  3

      (define foo
        (let ((x 4))
          (lambda (y) (+ x y))))
      (foo 6)                                 =>  10

special form: named-lambda formals expression expression ...
  The `named-lambda` special form is similar to `lambda`, except that the first "required parameter" in formals is not a parameter but the name of the resulting procedure; thus formals must have at least one required parameter. This name has no semantic meaning, but is included in the external representation of the procedure, making it useful for debugging. In MIT Scheme, `lambda` is implemented as `named-lambda`, with a special name that means "unnamed".

      (named-lambda (f x) (+ x x))    =>  #[compound-procedure 53 f]
      ((named-lambda (f x) (+ x x)) 4)        =>  8

[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

## 2.2 Lexical Binding

The three binding constructs `let`, `let*`, and `letrec`, give Scheme block structure. The syntax of the three constructs is identical, but they differ in the regions they establish for their variable bindings. In a `let` expression, the initial values are computed before any of the variables become bound. In a `let*` expression, the evaluations and bindings are sequentially interleaved. And in a `letrec` expression, all the bindings are in effect while the initial values are being computed (thus allowing mutually recursive definitions).

special form: let ((variable init) ...) expression expression ...
  The inits are evaluated in the current environment (in some unspecified order), the variables are bound to fresh locations holding the results, the expressions are evaluated sequentially in the extended environment, and the value of the last expression is returned. Each binding of a variable has the expressions as its region.

  MIT Scheme allows any of the inits to be omitted, in which case the corresponding variables are unassigned.

  Note that the following are equivalent:

      (let ((variable init) ...) expression expression ...)
      ((lambda (variable ...) expression expression ...) init ...)

  Some examples:

      (let ((x 2) (y 3))
        (* x y))                              =>  6

      (let ((x 2) (y 3))
        (let ((foo (lambda (z) (+ x y z)))
              (x 7))
          (foo 4)))                           =>  9

  See section 2.9 Iteration, for information on "named `let`".

special form: let* ((variable init) ...) expression expression ...
  `let*` is similar to `let`, but the bindings are performed sequentially from left to right, and the region of a binding is that part of the `let*` expression to the right of the binding. Thus the second binding is done in an environment in which the first binding is visible, and so on.

  Note that the following are equivalent:

      (let* ((variable1 init1)
             (variable2 init2)
             ...
             (variableN initN))
         expression
         expression ...)

      (let ((variable1 init1))
        (let ((variable2 init2))
          ...
            (let ((variableN initN))
              expression
              expression ...)
          ...))

  An example:

      (let ((x 2) (y 3))
        (let* ((x 7)
               (z (+ x y)))
          (* z x)))                           =>  70

special form: letrec ((variable init) ...) expression expression ...
  The variables are bound to fresh locations holding unassigned values, the inits are evaluated in the extended environment (in some unspecified order), each variable is assigned to the result of the corresponding init, the expressions are evaluated sequentially in the extended environment, and the value of the last expression is returned. Each binding of a variable has the entire `letrec` expression as its region, making it possible to define mutually recursive procedures.

  MIT Scheme allows any of the inits to be omitted, in which case the corresponding variables are unassigned.

      (letrec ((even?
                (lambda (n)
                  (if (zero? n)
                      #t
                      (odd? (- n 1)))))
               (odd?
                (lambda (n)
                  (if (zero? n)
                      #f
                      (even? (- n 1))))))
        (even? 88))                           =>  #t

  One restriction on `letrec` is very important: it shall be possible to evaluated each init without assigning or referring to the value of any variable. If this restriction is violated, then it is an error. The restriction is necessary because Scheme passes arguments by value rather than by name. In the most common uses of `letrec`, all the inits are `lambda` or `delay` expressions and the restriction is satisfied automatically.

[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

## 2.3 Dynamic Binding

special form: fluid-let ((variable init) ...) expression expression ...
  The inits are evaluated in the current environment (in some unspecified order), the current values of the variables are saved, the results are assigned to the variables, the expressions are evaluated sequentially in the current environment, the variables are restored to their original values, and the value of the last expression is returned.

  The syntax of this special form is similar to that of `let`, but `fluid-let` temporarily rebinds existing variables. Unlike `let`, `fluid-let` creates no new bindings; instead it assigns the value of each init to the binding (determined by the rules of lexical scoping) of its corresponding variable.

  MIT Scheme allows any of the inits to be omitted, in which case the corresponding variables are temporarily unassigned.

  An error of type `condition-type:unbound-variable` is signalled if any of the variables are unbound. However, because `fluid-let` operates by means of side effects, it is valid for any variable to be unassigned when the form is entered.

  Here is an example showing the difference between `fluid-let` and `let`. First see how `let` affects the binding of a variable:

      (define variable #t)
      (define (access-variable) variable)
      variable                                =>  #t
      (let ((variable #f))
        (access-variable))                    =>  #t
      variable                                =>  #t

  `access-variable` returns `#t` in this case because it is defined in an environment with `variable` bound to `#t`. `fluid-let`, on the other hand, temporarily reuses an existing variable:

      variable                                =>  #t
      (fluid-let ((variable #f))              ;reuses old binding
        (access-variable))                    =>  #f
      variable                                =>  #t

  The extent of a dynamic binding is defined to be the time period during which the variable contains the new value. Normally this time period begins when the body is entered and ends when it is exited; on a sequential machine it is normally a contiguous time period. However, because Scheme has first-class continuations, it is possible to leave the body and then reenter it, as many times as desired. In this situation, the extent becomes non-contiguous.

  When the body is exited by invoking a continuation, the new value is saved, and the variable is set to the old value. Then, if the body is reentered by invoking a continuation, the old value is saved, and the variable is set to the new value. In addition, side effects to the variable that occur both inside and outside of body are preserved, even if continuations are used to jump in and out of body repeatedly.

Here is a complicated example that shows the interaction between dynamic binding and continuations:

    (define (complicated-dynamic-binding)
      (let ((variable 1)
            (inside-continuation))
        (write-line variable)
        (call-with-current-continuation
         (lambda (outside-continuation)
           (fluid-let ((variable 2))
             (write-line variable)
             (set! variable 3)
             (call-with-current-continuation
              (lambda (k)
                (set! inside-continuation k)
                (outside-continuation #t)))
             (write-line variable)
             (set! inside-continuation #f))))
        (write-line variable)
        (if inside-continuation
            (begin
              (set! variable 4)
              (inside-continuation #f)))))

Evaluating ``(complicated-dynamic-binding)`' writes the following on the console:

    1
    2
    1
    3
    4

Commentary: the first two values written are the initial binding of `variable` and its new binding after the `fluid-let`'s body is entered. Immediately after they are written, `variable` is set to ``3`', and then `outside-continuation` is invoked, causing us to exit the body. At this point, ``1`' is written, demonstrating that the original value of `variable` has been restored, because we have left the body. Then we set `variable` to ``4`' and reenter the body by invoking `inside-continuation`. At this point, ``3`' is written, indicating that the side effect that previously occurred within the body has been preserved. Finally, we exit body normally, and write ``4`', demonstrating that the side effect that occurred outside of the body was also preserved.

[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

## 2.4 Definitions

special form: define variable [expression]
special form: define formals expression expression ...
  Definitions are valid in some but not all contexts where expressions are allowed. Definitions may only occur at the top level of a program and at the beginning of a lambda body (that is, the body of a `lambda`, `let`, `let*`, `letrec`, `fluid-let`, or "procedure `define`" expression). A definition that occurs at the top level of a program is called a top-level definition, and a definition that occurs at the beginning of a body is called an internal definition.

  In the second form of `define` (called "procedure `define`"), the component formals is identical to the component of the same name in a `named-lambda` expression. In fact, these two expressions are equivalent:

      (define (name1 name2 ...)
        expression
        expression ...)

      (define name1
        (named-lambda (name1 name2 ...)
          expression
          expression ...))

> 2.4.1 Top-Level Definitions |  |
> 2.4.2 Internal Definitions |  |

[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

### 2.4.1 Top-Level Definitions

A top-level definition,

    (define variable expression)

has essentially the same effect as this assignment expression, if variable is bound:

    (set! variable expression)

If variable is not bound, however, `define` binds variable to a new location in the current environment before performing the assignment (it is an error to perform a `set!` on an unbound variable). If you omit expression, the variable becomes unassigned; an attempt to reference such a variable is an error.

    (define add3
       (lambda (x) (+ x 3)))                =>  unspecified
    (add3 3)                                =>  6

    (define first car)                      =>  unspecified
    (first '(1 2))                          =>  1

    (define bar)                            =>  unspecified
    bar                                     error--> Unassigned variable

[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

### 2.4.2 Internal Definitions

An internal definition is a definition that occurs at the beginning of a body (that is, the body of a `lambda`, `let`, `let*`, `letrec`, `fluid-let`, or "procedure `define`" expression), rather than at the top level of a program. The variable defined by an internal definition is local to the body. That is, variable is bound rather than assigned, and the region of the binding is the entire body. For example,

    (let ((x 5))
      (define foo (lambda (y) (bar x y)))
      (define bar (lambda (a b) (+ (* a b) a)))
      (foo (+ x 3)))                        =>  45

A body containing internal definitions can always be converted into a completely equivalent `letrec` expression. For example, the `let` expression in the above example is equivalent to

    (let ((x 5))
      (letrec ((foo (lambda (y) (bar x y)))
               (bar (lambda (a b) (+ (* a b) a))))
        (foo (+ x 3))))

[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

## 2.5 Assignments

special form: set! variable [expression]
  If expression is specified, evaluates expression and stores the resulting value in the location to which variable is bound. If expression is omitted, variable is altered to be unassigned; a subsequent reference to such a variable is an error. In either case, the value of the `set!` expression is unspecified.

  Variable must be bound either in some region enclosing the `set!` expression, or at the top level. However, variable is permitted to be unassigned when the `set!` form is entered.

      (define x 2)                            =>  unspecified
      (+ x 1)                                 =>  3
      (set! x 4)                              =>  unspecified
      (+ x 1)                                 =>  5

  Variable may be an `access` expression (see section 13. Environments). This allows you to assign variables in an arbitrary environment. For example,

      (define x (let ((y 0)) (the-environment)))
      (define y 'a)
      y                                       =>  a
      (access y x)                            =>  0
      (set! (access y x) 1)                   =>  unspecified
      y                                       =>  a
      (access y x)                            =>  1

[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

## 2.6 Quoting

This section describes the expressions that are used to modify or prevent the evaluation of objects.

special form: quote datum
  `(quote datum)` evaluates to datum. Datum may be any external representation of a Scheme object (see section 1.2.6 External Representations). Use `quote` to include literal constants in Scheme code.

      (quote a)                               =>  a
      (quote #(a b c))                        =>  #(a b c)
      (quote (+ 1 2))                         =>  (+ 1 2)

  `(quote datum)` may be abbreviated as `'datum`. The two notations are equivalent in all respects.

      'a                                      =>  a
      '#(a b c)                               =>  #(a b c)
      '(+ 1 2)                                =>  (+ 1 2)
      '(quote a)                              =>  (quote a)
      ''a                                     =>  (quote a)

  Numeric constants, string constants, character constants, and boolean constants evaluate to themselves, so they don't need to be quoted.

      '"abc"                                  =>  "abc"
      "abc"                                   =>  "abc"
      '145932                                 =>  145932
      145932                                  =>  145932
      '#t                                     =>  #t
      #t                                      =>  #t
      '#\a                                    =>  #\a
      #\a                                     =>  #\a

special form: quasiquote template
  "Backquote" or "quasiquote" expressions are useful for constructing a list or vector structure when most but not all of the desired structure is known in advance. If no commas appear within the template, the result of evaluating ``template` is equivalent (in the sense of `equal?`) to the result of evaluating `'template`. If a comma appears within the template, however, the expression following the comma is evaluated ("unquoted") and its result is inserted into the structure instead of the comma and the expression. If a comma appears followed immediately by an at-sign (@), then the following expression shall evaluate to a list; the opening and closing parentheses of the list are then "stripped away" and the elements of the list are inserted in place of the comma at-sign expression sequence.

      `(list ,(+ 1 2) 4)                       =>  (list 3 4)

      (let ((name 'a)) `(list ,name ',name))   =>  (list a 'a)

      `(a ,(+ 1 2) ,@(map abs '(4 -5 6)) b)    =>  (a 3 4 5 6 b)

      `((foo ,(- 10 3)) ,@(cdr '(c)) . ,(car '(cons)))
                                               =>  ((foo 7) . cons)

      `#(10 5 ,(sqrt 4) ,@(map sqrt '(16 9)) 8)
                                               =>  #(10 5 2 4 3 8)

      `,(+ 2 3)                                =>  5

  Quasiquote forms may be nested. Substitutions are made only for unquoted components appearing at the same nesting level as the outermost backquote. The nesting level increases by one inside each successive quasiquotation, and decreases by one inside each unquotation.

      `(a `(b ,(+ 1 2) ,(foo ,(+ 1 3) d) e) f)
           =>  (a `(b ,(+ 1 2) ,(foo 4 d) e) f)

      (let ((name1 'x)
            (name2 'y))
         `(a `(b ,,name1 ,',name2 d) e))
           =>  (a `(b ,x ,'y d) e)

  The notations ``template` and (`quasiquote template`) are identical in all respects. `,expression` is identical to `(unquote expression)` and `,@expression` is identical to `(unquote-splicing expression)`.

      (quasiquote (list (unquote (+ 1 2)) 4))
           =>  (list 3 4)

      '(quasiquote (list (unquote (+ 1 2)) 4))
           =>  `(list ,(+ 1 2) 4)
           i.e., (quasiquote (list (unquote (+ 1 2)) 4))

  Unpredictable behavior can result if any of the symbols `quasiquote`, `unquote`, or `unquote-splicing` appear in a template in ways otherwise than as described above.

[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

## 2.7 Conditionals

The behavior of the conditional expressions is determined by whether objects are true or false. The conditional expressions count only `#f` as false. They count everything else, including `#t`, pairs, symbols, numbers, strings, vectors, and procedures as true (but see section 1.2.5 True and False).

In the descriptions that follow, we say that an object has "a true value" or "is true" when the conditional expressions treat it as true, and we say that an object has "a false value" or "is false" when the conditional expressions treat it as false.

special form: if predicate consequent [alternative]
  Predicate, consequent, and alternative are expressions. An `if` expression is evaluated as follows: first, predicate is evaluated. If it yields a true value, then consequent is evaluated and its value is returned. Otherwise alternative is evaluated and its value is returned. If predicate yields a false value and no alternative is specified, then the result of the expression is unspecified.

  An `if` expression evaluates either consequent or alternative, never both. Programs should not depend on the value of an `if` expression that has no alternative.

      (if (> 3 2) 'yes 'no)                   =>  yes
      (if (> 2 3) 'yes 'no)                   =>  no
      (if (> 3 2)
          (- 3 2)
          (+ 3 2))                            =>  1

special form: cond clause clause ...
  Each clause has this form:

      (predicate expression ...)

  where predicate is any expression. The last clause may be an `else` clause, which has the form:

      (else expression expression ...)

  A `cond` expression does the following:

  1. Evaluates the predicate expressions of successive clauses in order, until one of the predicates evaluates to a true value.

  2. When a predicate evaluates to a true value, `cond` evaluates the expressions in the associated clause in left to right order, and returns the result of evaluating the last expression in the clause as the result of the entire `cond` expression.

     If the selected clause contains only the predicate and no expressions, `cond` returns the value of the predicate as the result.

  3. If all predicates evaluate to false values, and there is no `else` clause, the result of the conditional expression is unspecified; if there is an `else` clause, `cond` evaluates its expressions (left to right) and returns the value of the last one.

      (cond ((> 3 2) 'greater)
            ((< 3 2) 'less))                  =>  greater

      (cond ((> 3 3) 'greater)
            ((< 3 3) 'less)
            (else 'equal))                    =>  equal

  Normally, programs should not depend on the value of a `cond` expression that has no `else` clause. However, some Scheme programmers prefer to write `cond` expressions in which at least one of the predicates is always true. In this style, the final clause is equivalent to an `else` clause.

  Scheme supports an alternative clause syntax:

      (predicate => recipient)

  where recipient is an expression. If predicate evaluates to a true value, then recipient is evaluated. Its value must be a procedure of one argument; this procedure is then invoked on the value of the predicate.

      (cond ((assv 'b '((a 1) (b 2))) => cadr)
            (else #f))                        =>  2

special form: case key clause clause ...
  Key may be any expression. Each clause has this form:

      ((object ...) expression expression ...)

  No object is evaluated, and all the objects must be distinct. The last clause may be an `else` clause, which has the form:

      (else expression expression ...)

  A `case` expression does the following:

  1. Evaluates key and compares the result with each object.

  2. If the result of evaluating key is equivalent (in the sense of `eqv?`; see section 3. Equivalence Predicates) to an object, `case` evaluates the expressions in the corresponding clause from left to right and returns the result of evaluating the last expression in the clause as the result of the `case` expression.

  3. If the result of evaluating key is different from every object, and if there's an `else` clause, `case` evaluates its expressions and returns the result of the last one as the result of the `case` expression. If there's no `else` clause, `case` returns an unspecified result. Programs should not depend on the value of a `case` expression that has no `else` clause.

  For example,

      (case (* 2 3)
         ((2 3 5 7) 'prime)
         ((1 4 6 8 9) 'composite))            =>  composite

      (case (car '(c d))
         ((a) 'a)
         ((b) 'b))                            =>  unspecified

      (case (car '(c d))
         ((a e i o u) 'vowel)
         ((w y) 'semivowel)
         (else 'consonant))                   =>  consonant

special form: and expression ...
  The expressions are evaluated from left to right, and the value of the first expression that evaluates to a false value is returned. Any remaining expressions are not evaluated. If all the expressions evaluate to true values, the value of the last expression is returned. If there are no expressions then `#t` is returned.

      (and (= 2 2) (> 2 1))                   =>  #t
      (and (= 2 2) (< 2 1))                   =>  #f
      (and 1 2 'c '(f g))                     =>  (f g)
      (and)                                   =>  #t

special form: or expression ...
  The expressions are evaluated from left to right, and the value of the first expression that evaluates to a true value is returned. Any remaining expressions are not evaluated. If all expressions evaluate to false values, the value of the last expression is returned. If there are no expressions then `#f` is returned.

      (or (= 2 2) (> 2 1))                    =>  #t
      (or (= 2 2) (< 2 1))                    =>  #t
      (or #f #f #f)                           =>  #f
      (or (memq 'b '(a b c)) (/ 3 0))         =>  (b c)

[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

## 2.8 Sequencing

The `begin` special form is used to evaluate expressions in a particular order.

special form: begin expression expression ...
  The expressions are evaluated sequentially from left to right, and the value of the last expression is returned. This expression type is used to sequence side effects such as input and output.

      (define x 0)
      (begin (set! x 5)
             (+ x 1))                 =>  6

      (begin (display "4 plus 1 equals ")
             (display (+ 4 1)))
                                      -|  4 plus 1 equals 5
                                      =>  unspecified

  Often the use of `begin` is unnecessary, because many special forms already support sequences of expressions (that is, they have an implicit `begin`). Some of these special forms are:

      case
      cond
      define          ;``procedure define'' only
      do
      fluid-let
      lambda
      let
      let*
      letrec
      named-lambda

  The obsolete special form `sequence` is identical to `begin`. It should not be used in new code.

[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

## 2.9 Iteration

The iteration expressions are: "named `let`" and `do`. They are also binding expressions, but are more commonly referred to as iteration expressions. Because Scheme is properly tail-recursive, you don't need to use these special forms to express iteration; you can simply use appropriately written "recursive" procedure calls.

special form: let name ((variable init) ...) expression expression ...
  MIT Scheme permits a variant on the syntax of `let` called "named `let`" which provides a more general looping construct than `do`, and may also be used to express recursions.

  Named `let` has the same syntax and semantics as ordinary `let` except that name is bound within the expressions to a procedure whose formal arguments are the variables and whose body is the expressions. Thus the execution of the expressions may be repeated by invoking the procedure named by name.

  MIT Scheme allows any of the inits to be omitted, in which case the corresponding variables are unassigned.

  Note: the following expressions are equivalent:

      (let name ((variable init) ...)
        expression
        expression ...)

      ((letrec ((name
                 (named-lambda (name variable ...)
                   expression
                   expression ...)))
         name)
       init ...)

  Here is an example:

      (let loop
           ((numbers '(3 -2 1 6 -5))
            (nonneg '())
            (neg '()))
        (cond ((null? numbers)
               (list nonneg neg))
              ((>= (car numbers) 0)
               (loop (cdr numbers)
                     (cons (car numbers) nonneg)
                     neg))
              (else
               (loop (cdr numbers)
                     nonneg
                     (cons (car numbers) neg)))))

           =>  ((6 1 3) (-5 -2))

special form: do ((variable init step) ...) (test expression ...) command ...
  `do` is an iteration construct. It specifies a set of variables to be bound, how they are to be initialized at the start, and how they are to be updated on each iteration. When a termination condition is met, the loop exits with a specified result value.

  `do` expressions are evaluated as follows: The init expressions are evaluated (in some unspecified order), the variables are bound to fresh locations, the results of the init expressions are stored in the bindings of the variables, and then the iteration phase begins.

  Each iteration begins by evaluating test; if the result is false, then the command expressions are evaluated in order for effect, the step expressions are evaluated in some unspecified order, the variables are bound to fresh locations, the results of the steps are stored in the bindings of the variables, and the next iteration begins.

  If test evaluates to a true value, then the expressions are evaluated from left to right and the value of the last expression is returned as the value of the `do` expression. If no expressions are present, then the value of the `do` expression is unspecified in standard Scheme; in MIT Scheme, the value of test is returned.

  The region of the binding of a variable consists of the entire `do` expression except for the inits. It is an error for a variable to appear more than once in the list of `do` variables.

  A step may be omitted, in which case the effect is the same as if `(variable init variable)` had been written instead of `(variable init)`.

      (do ((vec (make-vector 5))
            (i 0 (+ i 1)))
          ((= i 5) vec)
         (vector-set! vec i i))               =>  #(0 1 2 3 4)

      (let ((x '(1 3 5 7 9)))
         (do ((x x (cdr x))
              (sum 0 (+ sum (car x))))
             ((null? x) sum)))                =>  25

[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

## 2.10 Structure Definitions

This section provides examples and describes the options and syntax of `define-structure`, an MIT Scheme macro that is very similar to `defstruct` in Common Lisp. The differences between them are summarized at the end of this section. For more information, see Steele's Common Lisp book.

special form: define-structure (name structure-option ...) slot-description ...
  Each slot-description takes one of the following forms:

      slot-name
      (slot-name default-init [slot-option value]*)

  The fields name and slot-name must both be symbols. The field default-init is an expression for the initial value of the slot. It is evaluated each time a new instance is constructed. If it is not specified, the initial content of the slot is undefined. Default values are only useful with a BOA constructor with argument list or a keyword constructor (see below).

  Evaluation of a `define-structure` expression defines a structure descriptor and a set of procedures to manipulate instances of the structure. These instances are represented as records by default (see section 10.4 Records) but may alternately be lists or vectors. The accessors and modifiers are marked with compiler declarations so that calls to them are automatically transformed into appropriate references. Often, no options are required, so a simple call to `define-structure` looks like:

      (define-structure foo a b c)

  This defines a type descriptor `foo`, a constructor `make-foo`, a predicate `foo?`, accessors `foo-a`, `foo-b`, and `foo-c`, and modifiers `set-foo-a!`, `set-foo-b!`, and `set-foo-c!`.

  In general, if no options are specified, `define-structure` defines the following (using the simple call above as an example):

  type descriptor
    The name of the type descriptor is the same as the name of the structure, e.g. ``foo`'. The type descriptor satisfies the predicate `record-type?`.

  constructor
    The name of the constructor is `"make-"` followed by the name of the structure, e.g. ``make-foo`'. The number of arguments accepted by the constructor is the same as the number of slots; the arguments are the initial values for the slots, and the order of the arguments matches the order of the slot definitions.

  predicate
    The name of the predicate is the name of the structure followed by `"?"`, e.g. ``foo?`'. The predicate is a procedure of one argument, which returns `#t` if its argument is a record of the type defined by this structure definition, and `#f` otherwise.

  accessors
    For each slot, an accessor is defined. The name of the accessor is formed by appending the name of the structure, a hyphen, and the name of the slot, e.g. ``foo-a`'. The accessor is a procedure of one argument, which must be a record of the type defined by this structure definition. The accessor extracts the contents of the corresponding slot in that record and returns it.

  modifiers
    For each slot, a modifier is defined. The name of the modifier is formed by appending `"set-"`, the name of the accessor, and `"!"`, e.g. ``set-foo-a!`'. The modifier is a procedure of two arguments, the first of which must be a record of the type defined by this structure definition, and the second of which may be any object. The modifier modifies the contents of the corresponding slot in that record to be that object, and returns an unspecified value.

  When options are not supplied, `(name)` may be abbreviated to name. This convention holds equally for structure-options and slot-options. Hence, these are equivalent:

      (define-structure foo a b c)
      (define-structure (foo) (a) b (c))

  as are

      (define-structure (foo keyword-constructor) a b c)
      (define-structure (foo (keyword-constructor)) a b c)

  When specified as option values, `false` and `nil` are equivalent to `#f`, and `true` and `t` are equivalent to `#t`.

Possible slot-options are:

slot option: read-only value
  When given a value other than `#f`, this specifies that no modifier should be created for the slot.

slot option: type type-descriptor
  This is accepted but not presently used.

Possible structure-options are:

structure option: predicate [name]
  This option controls the definition of a predicate procedure for the structure. If name is not given, the predicate is defined with the default name (see above). If name is `#f`, the predicate is not defined at all. Otherwise, name must be a symbol, and the predicate is defined with that symbol as its name.

structure option: copier [name]
  This option controls the definition of a procedure to copy instances of the structure. This is a procedure of one argument, a structure instance, that makes a newly allocated copy of the structure and returns it. If name is not given, the copier is defined, and the name of the copier is `"copy-"` followed by the structure name (e.g. ``copy-foo`'). If name is `#f`, the copier is not defined. Otherwise, name must be a symbol, and the copier is defined with that symbol as its name.

structure option: print-procedure expression
  Evaluating expression must yield a procedure of two arguments, which is used to print instances of the structure. The procedure is an unparser method (see section 14.7 Custom Output). If the structure instances are records, this option has the same effect as calling `set-record-type-unparser-method!`.

structure option: constructor [name [argument-list]]
  This option controls the definition of constructor procedures. These constructor procedures are called "BOA constructors", for "By Order of Arguments", because the arguments to the constructor specify the initial contents the structure's slots by the order in which they are given. This is as opposed to "keyword constructors", which specify the initial contents using keywords, and in which the order of arguments is irrelevant.

  If name is not given, a constructor is defined with the default name and arguments (see above). If name is `#f`, no constructor is defined; argument-list may not be specified in this case. Otherwise, name must be a symbol, and a constructor is defined with that symbol as its name. If name is a symbol, argument-list is optionally allowed; if it is omitted, the constructor accepts one argument for each slot in the structure definition, in the same order in which the slots appear in the definition. Otherwise, argument-list must be a lambda list (see section 2.1 Lambda Expressions), and each of the parameters of the lambda list must be the name of a slot in the structure. The arguments accepted by the constructor are defined by this lambda list. Any slot that is not specified by the lambda list is initialized to the default-init as specified above; likewise for any slot specified as an optional parameter when the corresponding argument is not supplied.

  If the `constructor` option is specified, the default constructor is not defined. Additionally, the `constructor` option may be specified multiple times to define multiple constructors with different names and argument lists.

      (define-structure (foo
                         (constructor make-foo (#!optional a b)))
        (a 6 read-only #t)
        (b 9))

structure option: keyword-constructor [name]
  This option controls the definition of keyword constructor procedures. A keyword constructor is a procedure that accepts arguments that are alternating slot names and values. If name is omitted, a keyword constructor is defined, and the name of the constructor is `"make-"` followed by the name of the structure (e.g. ``make-foo`'). Otherwise, name must be a symbol, and a keyword constructor is defined with this symbol as its name.

  If the `keyword-constructor` option is specified, the default constructor is not defined. Additionally, the `keyword-constructor` option may be specified multiple times to define multiple keyword constructors; this is usually not done since such constructors would all be equivalent.

      (define-structure (foo (keyword-constructor make-bar)) a b)
      (foo-a (make-bar 'b 20 'a 19))         => 19

structure option: type-descriptor name
  This option cannot be used with the `type` or `named` options.

  By default, structures are implemented as records. The name of the structure is defined to hold the type descriptor of the record defined by the structure. The `type-descriptor` option specifies a different name to hold the type descriptor.

      (define-structure foo a b)
      foo             => #[record-type 18]

      (define-structure (bar (type-descriptor bar-rtd)) a b)
      bar             error--> Unbound variable: bar
      bar-rtd         => #[record-type 19]

structure option: conc-name [name]
  By default, the prefix for naming accessors and modifiers is the name of the structure followed by a hyphen. The `conc-name` option can be used to specify an alternative. If name is not given, the prefix is the name of the structure followed by a hyphen (the default). If name is `#f`, the slot names are used directly, without prefix. Otherwise, name must a symbol, and that symbol is used as the prefix.

      (define-structure (foo (conc-name moby/)) a b)

  defines accessors `moby/a` and `moby/b`, and modifiers `set-moby/a!` and `set-moby/b!`.

      (define-structure (foo (conc-name #f)) a b)

  defines accessors `a` and `b`, and modifiers `set-a!` and `set-b!`.

structure option: type representation-type
  This option cannot be used with the `type-descriptor` option.

  By default, structures are implemented as records. The `type` option overrides this default, allowing the programmer to specify that the structure be implemented using another data type. The option value representation-type specifies the alternate data type; it is allowed to be one of the symbols `vector` or `list`, and the data type used is the one corresponding to the symbol.

  If this option is given, and the `named` option is not specified, the representation will not be tagged, and neither a predicate nor a type descriptor will be defined; also, the `print-procedure` option may not be given.

      (define-structure (foo (type list)) a b)
      (make-foo 1 2)                          => (1 2)

structure option: named [expression]
  This is valid only in conjunction with the `type` option and specifies that the structure instances be tagged to make them identifiable as instances of this structure type. This option cannot be used with the `type-descriptor` option.

  In the usual case, where expression is not given, the `named` option causes a type descriptor and predicate to be defined for the structure (recall that the `type` option without `named` suppresses their definition), and also defines a default unparser method for the structure instances (which can be overridden by the `print-procedure` option). If the default unparser method is not wanted then the `print-procedure` option should be specified as `#F`. This causes the structure to be printed in its native representation, as a list or vector, which includes the type descriptor. The type descriptor is a unique object, not a record type, that describes the structure instances and is additionally stored in the structure instances to identify them: if the representation type is `vector`, the type descriptor is stored in the zero-th slot of the vector, and if the representation type is `list`, it is stored as the first element of the list.

      (define-structure (foo (type vector) named) a b c)
      (vector-ref (make-foo 1 2 3) 0) => #[structure-type 52]

  If expression is specified, it is an expression that is evaluated to yield a tag object. The expression is evaluated once when the structure definition is evaluated (to specify the unparser method), and again whenever a predicate or constructor is called. Because of this, expression is normally a variable reference or a constant. The value yielded by expression may be any object at all. That object is stored in the structure instances in the same place that the type descriptor is normally stored, as described above. If expression is specified, no type descriptor is defined, only a predicate.

      (define-structure (foo (type vector) (named 'foo)) a b c)
      (vector-ref (make-foo 1 2 3) 0) => foo

structure option: safe-accessors [boolean]
  This option allows the programmer to have some control over the safety of the slot accessors (and modifiers) generated by `define-structure`. If `safe-accessors` is not specified, or if boolean is `#f`, then the accessors are optimized for speed at the expense of safety; when compiled, the accessors will turn into very fast inline sequences, usually one to three machine instructions in length. However, if `safe-accessors` is specified and boolean is either omitted or `#t`, then the accessors are optimized for safety, will check the type and structure of their argument, and will be close-coded.

      (define-structure (foo safe-accessors) a b c)

structure option: initial-offset offset
  This is valid only in conjunction with the `type` option. Offset must be an exact non-negative integer and specifies the number of slots to leave open at the beginning of the structure instance before the specified slots are allocated. Specifying an offset of zero is equivalent to omitting the `initial-offset` option.

  If the `named` option is specified, the structure tag appears in the first slot, followed by the "offset" slots, and then the regular slots. Otherwise, the "offset" slots come first, followed by the regular slots.

      (define-structure (foo (type vector) (initial-offset 3))
        a b c)
      (make-foo 1 2 3)                => #(() () () 1 2 3)

The essential differences between MIT Scheme's `define-structure` and Common Lisp's `defstruct` are:

- The default constructor procedure takes positional arguments, in the same order as specified in the definition of the structure. A keyword constructor may be specified by giving the option `keyword-constructor`.

- BOA constructors are described using Scheme lambda lists. Since there is nothing corresponding to `&aux` in Scheme lambda lists, this functionality is not implemented.

- By default, no `copier` procedure is defined.

- The side-effect procedure corresponding to the accessor `foo` is given the name `set-foo!`.

- Keywords are ordinary symbols -- use `foo` instead of `:foo`.

- The option values `false`, `nil`, `true`, and `t` are treated as if the appropriate boolean constant had been specified instead.

- The `print-function` option is named `print-procedure`. Its argument is a procedure of two arguments (the unparser state and the structure instance) rather than three as in Common Lisp.

- By default, named structures are tagged with a unique object of some kind. In Common Lisp, the structures are tagged with symbols. This depends on the Common Lisp package system to help generate unique tags; MIT Scheme has no such way to generate unique symbols.

- The `named` option may optionally take an argument, which is normally the name of a variable (any expression may be used, but it is evaluated whenever the tag name is needed). If used, structure instances will be tagged with that variable's value. The variable must be defined when `define-structure` is evaluated.

- The `type` option is restricted to the values `vector` and `list`.

- The `include` option is not implemented.

[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

## 2.11 Macros

(This section is largely taken from the Revised^4 Report on the Algorithmic Language Scheme. The section on Syntactic Closures is derived from a document written by Chris Hanson. The section on Explicit Renaming is derived from a document written by William Clinger.)

Scheme programs can define and use new derived expression types, called macros. Program-defined expression types have the syntax

    (keyword datum ...)

where keyword is an identifier that uniquely determines the expression type. This identifier is called the syntactic keyword, or simply keyword, of the macro. The number of the datums, and their syntax, depends on the expression type.

Each instance of a macro is called a use of the macro. The set of rules that specifies how a use of a macro is transcribed into a more primitive expression is called the transformer of the macro.

MIT Scheme also supports anonymous syntactic keywords. This means that it's not necessary to binding a macro transformer to a syntactic keyword before it is used. Instead, any macro-transformer expression can appear as the first element of a form, and the form will be expanded by the transformer.

The macro definition facility consists of these parts:

- A set of expressions used to establish that certain identifiers are macro keywords, associate them with macro transformers, and control the scope within which a macro is defined.

- A standard high-level pattern language for specifying macro transformers, introduced by the `syntax-rules` special form.

- Two non-standard low-level languages for specifying macro transformers, syntactic closures and explicit renaming.

The syntactic keyword of a macro may shadow variable bindings, and local variable bindings may shadow keyword bindings. All macros defined using the pattern language are "hygienic" and "referentially transparent" and thus preserve Scheme's lexical scoping:

- If a macro transformer inserts a binding for an identifier (variable or keyword), the identifier will in effect be renamed throughout its scope to avoid conflicts with other identifiers.

- If a macro transformer inserts a free reference to an identifier, the reference refers to the binding that was visible where the transformer was specified, regardless of any local bindings that may surround the use of the macro.

> 2.11.1 Binding Constructs for Syntactic Keywords |  |
> 2.11.2 Pattern Language |  |
> 2.11.3 Syntactic Closures |  |
> 2.11.4 Explicit Renaming |  |

[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

### 2.11.1 Binding Constructs for Syntactic Keywords

`let-syntax`, `letrec-syntax`, `let*-syntax` and `define-syntax` are analogous to `let`, `letrec`, `let*` and `define`, but they bind syntactic keywords to macro transformers instead of binding variables to locations that contain values.

special form: let-syntax bindings expression expression ...
  Bindings should have the form

      ((keyword transformer-spec) ...)

  Each keyword is an identifier, each transformer-spec is a a macro-transformer expression, and the body is a sequence of one or more expressions. It is an error for a keyword to appear more than once in the list of keywords being bound.

  The expressions are expanded in the syntactic environment obtained by extending the syntactic environment of the `let-syntax` expression with macros whose keywords are the keywords, bound to the specified transformers. Each binding of a keyword has the expressions as its region.

      (let-syntax ((when (syntax-rules ()
                           ((when test stmt1 stmt2 ...)
                            (if test
                                (begin stmt1
                                       stmt2 ...))))))
        (let ((if #t))
          (when if (set! if 'now))
          if))                           =>  now

      (let ((x 'outer))
        (let-syntax ((m (syntax-rules () ((m) x))))
          (let ((x 'inner))
            (m))))                       =>  outer

special form: letrec-syntax bindings expression expression ...
  The syntax of `letrec-syntax` is the same as for `let-syntax`.

  The expressions are expanded in the syntactic environment obtained by extending the syntactic environment of the `letrec-syntax` expression with macros whose keywords are the keywords, bound to the specified transformers. Each binding of a keyword has the bindings as well as the expressions within its region, so the transformers can transcribe expressions into uses of the macros introduced by the `letrec-syntax` expression.

      (letrec-syntax
        ((my-or (syntax-rules ()
                  ((my-or) #f)
                  ((my-or e) e)
                  ((my-or e1 e2 ...)
                   (let ((temp e1))
                     (if temp
                         temp
                         (my-or e2 ...)))))))
        (let ((x #f)
              (y 7)
              (temp 8)
              (let odd?)
              (if even?))
          (my-or x
                 (let temp)
                 (if y)
                 y)))        =>  7

special form: let*-syntax bindings expression expression ...
  The syntax of `let*-syntax` is the same as for `let-syntax`.

  The expressions are expanded in the syntactic environment obtained by extending the syntactic environment of the `letrec-syntax` expression with macros whose keywords are the keywords, bound to the specified transformers. Each binding of a keyword has the subsequent bindings as well as the expressions within its region. Thus

      (let*-syntax
         ((a (syntax-rules ...))
          (b (syntax-rules ...)))
        ...)

  is equivalent to

      (let-syntax ((a (syntax-rules ...)))
        (let-syntax ((b (syntax-rules ...)))
          ...))

special form: define-syntax keyword transformer-spec
  Keyword is an identifier, and transformer-spec is a macro transformer expression. The syntactic environment is extended by binding the keyword to the specified transformer.

  The region of the binding introduced by `define-syntax` is the entire block in which it appears. However, the keyword may only be used after it has been defined.

  MIT Scheme permits `define-syntax` to appear both at top level and within `lambda` bodies. The Revised^4 Report permits only top-level uses of `define-syntax`.

  When compiling a program, a top-level instance of `define-syntax` both defines the syntactic keyword and generates code that will redefine the keyword when the program is loaded. This means that the same syntax can be used for defining macros that will be used during compilation and for defining macros to be used at run time.

  Although macros may expand into definitions and syntax definitions in any context that permits them, it is an error for a definition or syntax definition to shadow a syntactic keyword whose meaning is needed to determine whether some form in the group of forms that contains the shadowing definition is in fact a definition, or, for internal definitions, is needed to determine the boundary between the group and the expressions that follow the group. For example, the following are errors:

      (define define 3)

      (begin (define begin list))

      (let-syntax
        ((foo (syntax-rules ()
                ((foo (proc args ...) body ...)
                 (define proc
                   (lambda (args ...)
                     body ...))))))
        (let ((x 3))
          (foo (plus x y) (+ x y))
          (define foo x)
          (plus foo x)))

[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

### 2.11.2 Pattern Language

MIT Scheme supports a high-level pattern language for specifying macro transformers. This pattern language is defined by the Revised^4 Report and is portable to other conforming Scheme implementations. To use the pattern language, specify a transformer-spec as a `syntax-rules` form:

special form: syntax-rules literals syntax-rule ...
  Literals is a list of identifiers and each syntax-rule should be of the form

      (pattern template)

  The pattern in a syntax-rule is a list pattern that begins with the keyword for the macro.

  A pattern is either an identifier, a constant, or one of the following

      (pattern ...)
      (pattern pattern ... . pattern)
      (pattern ... pattern ellipsis)

  and a template is either an identifier, a constant, or one of the following

      (element ...)
      (element element ... . template)

  where an element is a template optionally followed by an ellipsis and an ellipsis is the identifier ``...`' (which cannot be used as an identifier in either a template or a pattern).

  An instance of `syntax-rules` produces a new macro transformer by specifying a sequence of hygienic rewrite rules. A use of a macro whose keyword is associated with a transformer specified by `syntax-rules` is matched against the patterns contained in the syntax-rules, beginning with the leftmost syntax-rule. When a match is found, the macro use is transcribed hygienically according to the template.

  An identifier that appears in the pattern of a syntax-rule is a pattern-variable, unless it is the keyword that begins the pattern, is listed in literals, or is the identifier ``...`'. Pattern variables match arbitrary input elements and are used to refer to elements of the input in the template. It is an error for the same pattern variable to appear more than once in a pattern.

  The keyword at the beginning of the pattern in a syntax-rule is not involved in the matching and is not considered a pattern variable or literal identifier.

  Identifiers that appear in literals are interpreted as literal identifiers to be matched against corresponding subforms of the input. A subform in the input matches a literal identifier if and only if it is an identifier and either both its occurrence in the macro expression and its occurrence in the macro definition have the same lexical binding, or the two identifiers are equal and both have no lexical binding.

  A subpattern followed by `...` can match zero or more elements of the input. It is an error for `...` to appear in literals. Within a pattern the identifier `...` must follow the last element of a nonempty sequence of subpatterns.

  More formally, an input form F matches a pattern P if and only if:

  - P is a non-literal identifier; or

  - P is a literal identifier and F is an identifier with the same binding; or

  - P is a list `(P_1 ... P_n)` and F is a list of n forms that match P_1 through P_n, respectively; or

  - P is an improper list `(P_1 P_2 ... P_n . P_n+1)` and F is a list or improper list of n or more forms that match P_1 through P_n, respectively, and whose nth "cdr" matches P_n+1; or

  - P is of the form `(P_1 ... P_n P_n+1 ellipsis)` where ellipsis is the identifier `...` and F is a proper list of at least n forms, the first n of which match P_1 through P_n, respectively, and each remaining element of F matches P_n+1; or

  - P is a datum and F is equal to P in the sense of the `equal?` procedure.

  It is an error to use a macro keyword, within the scope of its binding, in an expression that does not match any of the patterns.

  When a macro use is transcribed according to the template of the matching syntax rule, pattern variables that occur in the template are replaced by the subforms they match in the input. Pattern variables that occur in subpatterns followed by one or more instances of the identifier `...` are allowed only in subtemplates that are followed by as many instances of `...`. They are replaced in the output by all of the subforms they match in the input, distributed as indicated. It is an error if the output cannot be built up as specified.

  Identifiers that appear in the template but are not pattern variables or the identifier `...` are inserted into the output as literal identifiers. If a literal identifier is inserted as a free identifier then it refers to the binding of that identifier within whose scope the instance of `syntax-rules` appears. If a literal identifier is inserted as a bound identifier then it is in effect renamed to prevent inadvertent captures of free identifiers.

      (let ((=> #f))
        (cond (#t => 'ok)))           => ok

  The macro transformer for `cond` recognizes `=>` as a local variable, and hence an expression, and not as the top-level identifier `=>`, which the macro transformer treats as a syntactic keyword. Thus the example expands into

      (let ((=> #f))
        (if #t (begin => 'ok)))

  instead of

      (let ((=> #f))
        (let ((temp #t))
          (if temp
              ('ok temp))))

  which would result in an invalid procedure call.

[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

### 2.11.3 Syntactic Closures

MIT Scheme's syntax-transformation engine is an implementation of syntactic closures, a mechanism invented by Alan Bawden and Jonathan Rees. The main feature of the syntactic-closures mechanism is its simplicity and its close relationship to the environment models commonly used with Scheme. Using the mechanism to write macro transformers is somewhat cumbersome and can be confusing for the newly initiated, but it is easily mastered.

> 2.11.3.1 Syntax Terminology |  |
> 2.11.3.2 Transformer Definition |  |
> 2.11.3.3 Identifiers |  |

[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

#### 2.11.3.1 Syntax Terminology

This section defines the concepts and data types used by the syntactic closures facility.

- Forms are the syntactic entities out of which programs are recursively constructed. A form is any expression, any definition, any syntactic keyword, or any syntactic closure. The variable name that appears in a `set!` special form is also a form. Examples of forms:

      17
      #t
      car
      (+ x 4)
      (lambda (x) x)
      (define pi 3.14159)
      if
      define

- An alias is an alternate name for a given symbol. It can appear anywhere in a form that the symbol could be used, and when quoted it is replaced by the symbol; however, it does not satisfy the predicate `symbol?`. Macro transformers rarely distinguish symbols from aliases, referring to both as identifiers. Another name for an alias is synthetic identifier; this document uses both names.

- A syntactic environment maps identifiers to their meanings. More precisely, it determines whether an identifier is a syntactic keyword or a variable. If it is a keyword, the meaning is an interpretation for the form in which that keyword appears. If it is a variable, the meaning identifies which binding of that variable is referenced. In short, syntactic environments contain all of the contextual information necessary for interpreting the meaning of a particular form.

- A syntactic closure consists of a form, a syntactic environment, and a list of identifiers. All identifiers in the form take their meaning from the syntactic environment, except those in the given list. The identifiers in the list are to have their meanings determined later.

  A syntactic closure may be used in any context in which its form could have been used. Since a syntactic closure is also a form, it may not be used in contexts where a form would be illegal. For example, a form may not appear as a clause in the `cond` special form.

  A syntactic closure appearing in a quoted structure is replaced by its form.

[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

#### 2.11.3.2 Transformer Definition

This section describes the special forms for defining syntactic-closures macro transformers, and the associated procedures for manipulating syntactic closures and syntactic environments.

special form: sc-macro-transformer expression
  The expression is expanded in the syntactic environment of the `sc-macro-transformer` expression, and the expanded expression is evaluated in the transformer environment to yield a macro transformer as described below. This macro transformer is bound to a macro keyword by the special form in which the `transformer` expression appears (for example, `let-syntax`).

  In the syntactic closures facility, a macro transformer is a procedure that takes two arguments, a form and a syntactic environment, and returns a new form. The first argument, the input form, is the form in which the macro keyword occurred. The second argument, the usage environment, is the syntactic environment in which the input form occurred. The result of the transformer, the output form, is automatically closed in the transformer environment, which is the syntactic environment in which the `transformer` expression occurred.

  For example, here is a definition of a `push` macro using `syntax-rules`:

      (define-syntax push
        (syntax-rules ()
          ((push item list)
           (set! list (cons item list)))))

  Here is an equivalent definition using `sc-macro-transformer`:

      (define-syntax push
        (sc-macro-transformer
         (lambda (exp env)
           (let ((item (make-syntactic-closure env '() (cadr exp)))
                 (list (make-syntactic-closure env '() (caddr exp))))
             `(set! ,list (cons ,item ,list))))))

  In this example, the identifiers `set!` and `cons` are closed in the transformer environment, and thus will not be affected by the meanings of those identifiers in the usage environment `env`.

  Some macros may be non-hygienic by design. For example, the following defines a `loop` macro that implicitly binds `exit` to an escape procedure. The binding of `exit` is intended to capture free references to `exit` in the body of the loop, so `exit` must be left free when the body is closed:

      (define-syntax loop
        (sc-macro-transformer
         (lambda (exp env)
           (let ((body (cdr exp)))
             `(call-with-current-continuation
               (lambda (exit)
                 (let f ()
                   ,@(map (lambda (exp)
                            (make-syntactic-closure env '(exit)
                              exp))
                          body)
                   (f))))))))

special form: rsc-macro-transformer expression
  This form is an alternative way to define a syntactic-closures macro transformer. Its syntax and usage are identical to `sc-macro-transformer`, except that the roles of the usage environment and transformer environment are reversed. (Hence RSC stands for Reversed Syntactic Closures.) In other words, the procedure specified by expression still accepts two arguments, but its second argument will be the transformer environment rather than the usage environment, and the returned expression is closed in the usage environment rather than the transformer environment.

  The advantage of this arrangement is that it allows a simpler definition style in some situations. For example, here is the `push` macro from above, rewritten in this style:

      (define-syntax push
        (rsc-macro-transformer
         (lambda (exp env)
           `(,(make-syntactic-closure env '() 'SET!)
             ,(caddr exp)
             (,(make-syntactic-closure env '() 'CONS)
              ,(cadr exp)
              ,(caddr exp))))))

  In this style only the introduced keywords are closed, while everything else remains open.

  Note that `rsc-macro-transformer` and `sc-macro-transformer` are easily interchangeable. Here is how to emulate `rsc-macro-transformer` using `sc-macro-transformer`. (This technique can be used to effect the opposite emulation as well.)

      (define-syntax push
        (sc-macro-transformer
         (lambda (exp usage-env)
           (capture-syntactic-environment
            (lambda (env)
              (make-syntactic-closure usage-env '()
                `(,(make-syntactic-closure env '() 'SET!)
                  ,(caddr exp)
                  (,(make-syntactic-closure env '() 'CONS)
                   ,(cadr exp)
                   ,(caddr exp)))))))))

To assign meanings to the identifiers in a form, use `make-syntactic-closure` to close the form in a syntactic environment.

procedure: make-syntactic-closure environment free-names form
  Environment must be a syntactic environment, free-names must be a list of identifiers, and form must be a form. `make-syntactic-closure` constructs and returns a syntactic closure of form in environment, which can be used anywhere that form could have been used. All the identifiers used in form, except those explicitly excepted by free-names, obtain their meanings from environment.

  Here is an example where free-names is something other than the empty list. It is instructive to compare the use of free-names in this example with its use in the `loop` example above: the examples are similar except for the source of the identifier being left free.

      (define-syntax let1
        (sc-macro-transformer
         (lambda (exp env)
           (let ((id (cadr exp))
                 (init (caddr exp))
                 (exp (cadddr exp)))
             `((lambda (,id)
                 ,(make-syntactic-closure env (list id) exp))
               ,(make-syntactic-closure env '() init))))))

  `let1` is a simplified version of `let` that only binds a single identifier, and whose body consists of a single expression. When the body expression is syntactically closed in its original syntactic environment, the identifier that is to be bound by `let1` must be left free, so that it can be properly captured by the `lambda` in the output form.

In most situations, the free-names argument to `make-syntactic-closure` is the empty list. In those cases, the more succinct `close-syntax` can be used:

procedure: close-syntax form environment
  Environment must be a syntactic environment and form must be a form. Returns a new syntactic closure of form in environment, with no free names. Entirely equivalent to

      (make-syntactic-closure environment '() form)

To obtain a syntactic environment other than the usage environment, use `capture-syntactic-environment`.

procedure: capture-syntactic-environment procedure
  `capture-syntactic-environment` returns a form that will, when transformed, call procedure on the current syntactic environment. Procedure should compute and return a new form to be transformed, in that same syntactic environment, in place of the form.

  An example will make this clear. Suppose we wanted to define a simple `loop-until` keyword equivalent to

      (define-syntax loop-until
        (syntax-rules ()
          ((loop-until id init test return step)
           (letrec ((loop
                     (lambda (id)
                       (if test return (loop step)))))
             (loop init)))))

  The following attempt at defining `loop-until` has a subtle bug:

      (define-syntax loop-until
        (sc-macro-transformer
         (lambda (exp env)
           (let ((id (cadr exp))
                 (init (caddr exp))
                 (test (cadddr exp))
                 (return (cadddr (cdr exp)))
                 (step (cadddr (cddr exp)))
                 (close
                  (lambda (exp free)
                    (make-syntactic-closure env free exp))))
             `(letrec ((loop
                        (lambda (,id)
                          (if ,(close test (list id))
                              ,(close return (list id))
                              (loop ,(close step (list id)))))))
                (loop ,(close init '())))))))

  This definition appears to take all of the proper precautions to prevent unintended captures. It carefully closes the subexpressions in their original syntactic environment and it leaves the `id` identifier free in the `test`, `return`, and `step` expressions, so that it will be captured by the binding introduced by the `lambda` expression. Unfortunately it uses the identifiers `if` and `loop` within that `lambda` expression, so if the user of `loop-until` just happens to use, say, `if` for the identifier, it will be inadvertently captured.

  The syntactic environment that `if` and `loop` want to be exposed to is the one just outside the `lambda` expression: before the user's identifier is added to the syntactic environment, but after the identifier `loop` has been added. `capture-syntactic-environment` captures exactly that environment as follows:

      (define-syntax loop-until
        (sc-macro-transformer
         (lambda (exp env)
           (let ((id (cadr exp))
                 (init (caddr exp))
                 (test (cadddr exp))
                 (return (cadddr (cdr exp)))
                 (step (cadddr (cddr exp)))
                 (close
                  (lambda (exp free)
                    (make-syntactic-closure env free exp))))
             `(letrec ((loop
                        ,(capture-syntactic-environment
                          (lambda (env)
                            `(lambda (,id)
                               (,(make-syntactic-closure env '() `if)
                                ,(close test (list id))
                                ,(close return (list id))
                                (,(make-syntactic-closure env '() `loop)
                                 ,(close step (list id)))))))))
                (loop ,(close init '())))))))

  In this case, having captured the desired syntactic environment, it is convenient to construct syntactic closures of the identifiers `if` and the `loop` and use them in the body of the `lambda`.

  A common use of `capture-syntactic-environment` is to get the transformer environment of a macro transformer:

      (sc-macro-transformer
       (lambda (exp env)
         (capture-syntactic-environment
          (lambda (transformer-env)
            ...))))

[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

#### 2.11.3.3 Identifiers

This section describes the procedures that create and manipulate identifiers. The identifier data type extends the syntactic closures facility to be compatible with the high-level `syntax-rules` facility.

As discussed earlier, an identifier is either a symbol or an alias. An alias is implemented as a syntactic closure whose form is an identifier:

    (make-syntactic-closure env '() 'a) => an alias

Aliases are implemented as syntactic closures because they behave just like syntactic closures most of the time. The difference is that an alias may be bound to a new value (for example by `lambda` or `let-syntax`); other syntactic closures may not be used this way. If an alias is bound, then within the scope of that binding it is looked up in the syntactic environment just like any other identifier.

Aliases are used in the implementation of the high-level facility `syntax-rules`. A macro transformer created by `syntax-rules` uses a template to generate its output form, substituting subforms of the input form into the template. In a syntactic closures implementation, all of the symbols in the template are replaced by aliases closed in the transformer environment, while the output form itself is closed in the usage environment. This guarantees that the macro transformation is hygienic, without requiring the transformer to know the syntactic roles of the substituted input subforms.

procedure: identifier? object
  Returns `#t` if object is an identifier, otherwise returns `#f`. Examples:

      (identifier? 'a)        => #t
      (identifier? (make-syntactic-closure env '() 'a))
                              => #t

      (identifier? "a")       => #f
      (identifier? #\a)       => #f
      (identifier? 97)        => #f
      (identifier? #f)        => #f
      (identifier? '(a))      => #f
      (identifier? '#(a))     => #f

The predicate `eq?` is used to determine if two identifers are "the same". Thus `eq?` can be used to compare identifiers exactly as it would be used to compare symbols. Often, though, it is useful to know whether two identifiers "mean the same thing". For example, the `cond` macro uses the symbol `else` to identify the final clause in the conditional. A macro transformer for `cond` cannot just look for the symbol `else`, because the `cond` form might be the output of another macro transformer that replaced the symbol `else` with an alias. Instead the transformer must look for an identifier that "means the same thing" in the usage environment as the symbol `else` means in the transformer environment.

procedure: identifier=? environment1 identifier1 environment2 identifier2
  Environment1 and environment2 must be syntactic environments, and identifier1 and identifier2 must be identifiers. `identifier=?` returns `#t` if the meaning of identifier1 in environment1 is the same as that of identifier2 in environment2, otherwise it returns `#f`. Examples:

      (let-syntax
          ((foo
            (sc-macro-transformer
             (lambda (form env)
               (capture-syntactic-environment
                (lambda (transformer-env)
                  (identifier=? transformer-env 'x env 'x)))))))
        (list (foo)
              (let ((x 3))
                (foo))))
                              => (#t #f)

      (let-syntax ((bar foo))
        (let-syntax
            ((foo
              (sc-macro-transformer
               (lambda (form env)
                 (capture-syntactic-environment
                  (lambda (transformer-env)
                    (identifier=? transformer-env 'foo
                                  env (cadr form))))))))
          (list (foo foo)
                (foo bar))))
                              => (#f #t)

Sometimes it is useful to be able to introduce a new identifier that is guaranteed to be different from any existing identifier, similarly to the way that `generate-uninterned-symbol` is used.

procedure: make-synthetic-identifier identifier
  Creates and returns and new synthetic identifier (alias) that is guaranteed to be different from all existing identifiers. Identifier is any existing identifier, which is used in deriving the name of the new identifier.

  This is implemented by syntactically closing identifier in a special empty environment.

[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

### 2.11.4 Explicit Renaming

Explicit renaming is an alternative facility for defining macro transformers. In the MIT Scheme implementation, explicit-renaming transformers are implemented as an abstraction layer on top of syntactic closures. An explicit-renaming macro transformer is defined by an instance of the `er-macro-transformer` keyword:

special form: er-macro-transformer expression
  The expression is expanded in the syntactic environment of the `er-macro-transformer` expression, and the expanded expression is evaluated in the transformer environment to yield a macro transformer as described below. This macro transformer is bound to a macro keyword by the special form in which the `transformer` expression appears (for example, `let-syntax`).

  In the explicit-renaming facility, a macro transformer is a procedure that takes three arguments, a form, a renaming procedure, and a comparison predicate, and returns a new form. The first argument, the input form, is the form in which the macro keyword occurred.

  The second argument to a transformation procedure is a renaming procedure that takes the representation of an identifier as its argument and returns the representation of a fresh identifier that occurs nowhere else in the program. For example, the transformation procedure for a simplified version of the `let` macro might be written as

      (lambda (exp rename compare)
        (let ((vars (map car (cadr exp)))
              (inits (map cadr (cadr exp)))
              (body (cddr exp)))
          `((lambda ,vars ,@body)
            ,@inits)))

  This would not be hygienic, however. A hygienic `let` macro must rename the identifier `lambda` to protect it from being captured by a local binding. The renaming effectively creates an fresh alias for `lambda`, one that cannot be captured by any subsequent binding:

      (lambda (exp rename compare)
        (let ((vars (map car (cadr exp)))
              (inits (map cadr (cadr exp)))
              (body (cddr exp)))
          `((,(rename 'lambda) ,vars ,@body)
            ,@inits)))

  The expression returned by the transformation procedure will be expanded in the syntactic environment obtained from the syntactic environment of the macro application by binding any fresh identifiers generated by the renaming procedure to the denotations of the original identifiers in the syntactic environment in which the macro was defined. This means that a renamed identifier will denote the same thing as the original identifier unless the transformation procedure that renamed the identifier placed an occurrence of it in a binding position.

  The renaming procedure acts as a mathematical function in the sense that the identifiers obtained from any two calls with the same argument will be the same in the sense of `eqv?`. It is an error if the renaming procedure is called after the transformation procedure has returned.

  The third argument to a transformation procedure is a comparison predicate that takes the representations of two identifiers as its arguments and returns true if and only if they denote the same thing in the syntactic environment that will be used to expand the transformed macro application. For example, the transformation procedure for a simplified version of the `cond` macro can be written as

      (lambda (exp rename compare)
        (let ((clauses (cdr exp)))
          (if (null? clauses)
              `(,(rename 'quote) unspecified)
              (let* ((first (car clauses))
                     (rest (cdr clauses))
                     (test (car first)))
                (cond ((and (identifier? test)
                            (compare test (rename 'else)))
                       `(,(rename 'begin) ,@(cdr first)))
                      (else `(,(rename 'if)
                              ,test
                               (,(rename 'begin) ,@(cdr first))
                               (cond ,@rest))))))))))

  In this example the identifier `else` is renamed before being passed to the comparison predicate, so the comparison will be true if and only if the test expression is an identifier that denotes the same thing in the syntactic environment of the expression being transformed as `else` denotes in the syntactic environment in which the `cond` macro was defined. If `else` were not renamed before being passed to the comparison predicate, then it would match a local variable that happened to be named `else`, and the macro would not be hygienic.

  Some macros are non-hygienic by design. For example, the following defines a `loop` macro that implicitly binds `exit` to an escape procedure. The binding of `exit` is intended to capture free references to `exit` in the body of the loop, so `exit` is not renamed.

      (define-syntax loop
        (er-macro-transformer
         (lambda (x r c)
           (let ((body (cdr x)))
             `(,(r 'call-with-current-continuation)
               (,(r 'lambda) (exit)
                (,(r 'let) ,(r 'f) () ,@body (,(r 'f)))))))))

  Suppose a `while` macro is implemented using `loop`, with the intent that `exit` may be used to escape from the `while` loop. The `while` macro cannot be written as

      (define-syntax while
        (syntax-rules ()
          ((while test body ...)
           (loop (if (not test) (exit #f))
                 body ...))))

  because the reference to `exit` that is inserted by the `while` macro is intended to be captured by the binding of `exit` that will be inserted by the `loop` macro. In other words, this `while` macro is not hygienic. Like `loop`, it must be written using the `er-macro-transformer` syntax:

      (define-syntax while
        (er-macro-transformer
         (lambda (x r c)
           (let ((test (cadr x))
                 (body (cddr x)))
             `(,(r 'loop)
               (,(r 'if) (,(r 'not) ,test) (exit #f))
               ,@body)))))

[ << ] | [ >> ] |  |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

This document was generated by Chris Hanson on June, 17 2002 using texi2html