Next: , Previous: , Up: baselib   [Index]


4.17 Binding constructs for syntactic keywords

The let-syntax and letrec-syntax forms bind keywords. Like a begin form, a let-syntax or letrec-syntax form may appear in a definition context, in which case it is treated as a definition, and the forms in the body must also be definitions. A let-syntax or letrec-syntax form may also appear in an expression context, in which case the forms within their bodies must be expressions.

Syntax: let-syntax ?bindings ?form

?bindings must have the form:

((?keyword ?expression) …)

Each ?keyword is an identifier, and each ?expression is an expression that evaluates, at macro–expansion time, to a transformer. Transformers may be created by syntax-rules or identifier-syntax or by one of the other mechanisms described in Syntax–case. It is a syntax violation for ?keyword to appear more than once in the list of keywords being bound.

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

The ?forms of a let-syntax form are treated, whether in definition or expression context, as if wrapped in an implicit begin. Thus definitions in the result of expanding the ?forms have the same region as any definition appearing in place of the let-syntax form would have.

Implementation responsibilities: The implementation should detect if the value of ?expression cannot possibly be a transformer.

(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

(let ()
  (let-syntax ((def (syntax-rules ()
                      ((def stuff ...) (define stuff ...)))))
    (def foo 42))
  foo)
⇒ 42

(let ()
  (let-syntax ())
  5)
⇒ 5
Syntax: letrec-syntax ?bindings ?form

Same as for let-syntax.

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

The ?forms of a letrec-syntax form are treated, whether in definition or expression context, as if wrapped in an implicit begin. Thus definitions in the result of expanding the ?forms have the same region as any definition appearing in place of the letrec-syntax form would have.

Implementation responsibilities: The implementation should detect if the value of ?expression cannot possibly be a transformer.

(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

The following example highlights how let-syntax and letrec-syntax differ.

(let ((f (lambda (x) (+ x 1))))
  (let-syntax ((f (syntax-rules ()
                    ((f x) x)))
               (g (syntax-rules ()
                    ((g x) (f x)))))
    (list (f 1) (g 1))))
⇒ (1 2)

(let ((f (lambda (x) (+ x 1))))
  (letrec-syntax ((f (syntax-rules ()
                       ((f x) x)))
                  (g (syntax-rules ()
                       ((g x) (f x)))))
    (list (f 1) (g 1))))
⇒ (1 1)

The two expressions are identical except that the let-syntax form in the first expression is a letrec-syntax form in the second. In the first expression, the ‘f’ occurring in ‘g’ refers to the let–bound variable ‘f’, whereas in the second it refers to the keyword f whose binding is established by the letrec-syntax form.


Next: , Previous: , Up: baselib   [Index]