Next: Pattern Language, Previous: Macros, Up: Macros [Contents][Index]
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.
Any argument named transformer-spec must be a macro-transformer expression, which is one of the following:
syntax-rules
.
sc-macro-transformer
,
rsc-macro-transformer
, or er-macro-transformer
.
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
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
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 …))) …))
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/GNU 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)))
Next: Pattern Language, Previous: Macros, Up: Macros [Contents][Index]