[R6RS] The (rnrs syntax-case (6))
library provides support for
writing low-level macros in a high-level style, with automatic syntax checking,
input destructuring, output restructuring, maintenance of lexical scoping and
referential transparency (hygiene), and support for controlled identifier capture.
[R6RS] Each literal must be an identifier. Each clause must take one of the following two forms.
(_pattern_ _output-expression_)
(_pattern_ _fender_ _output-expression_)
Fender and output-expression must be expressions.
Pattern is the same as syntax-rules
. See
(rnrs base (6)) section.
A syntax-case
expression first evaluates expression. It then attempts to
match the pattern from the first clause against the resulting value,
which is unwrapped as necessary to perform the match. If the _pattern_matches the value and no fender is present, output-expression is
evaluated and its value returned as the value of the syntax-case
expression.
If the pattern does not match the value, syntax-case
tries the second
clause, then the third, and so on. It is a syntax violation if the value
does not match any of the patterns.
If the optional fender is present, it serves as an additional constraint on acceptance of a clause. If the pattern of a given clause matches the input value, the corresponding fender is evaluated. If fender evaluates to a true value, the clause is accepted; otherwise, the clause is rejected as if the pattern had failed to match the value. Fenders are logically a part of the matching process, i.e., they specify additional matching constraints beyond the basic structure of the input.
Pattern variables contained within a clause's pattern are bound to the corresponding pieces of the input value within the clause's fender (if present) and output-expression. Pattern variables can be referenced only within syntax expressions (see below). Pattern variables occupy the same name space as program variables and keywords.
If the syntax-case
form is in tail context, the output-expressions
are also in tail position.
[R6RS] A template is a pattern variable, an identifier that is not a pattern variable, a pattern datum, or one of the following.
(_subtemplate_ ...)
(_subtemplate_ ... . _template_)
#(_subtemplate_ ...)
A subtemplate is a template followed by zero or more ellipses.
The value of a syntax
form is a copy of template in which the
pattern variables appearing within the template are replaced with the input
subforms to which they are bound. Pattern data and identifiers that are not
pattern variables or ellipses are copied directly into the output. A
subtemplate followed by an ellipsis expands into zero or more occurrences
of the subtemplate. Pattern variables that occur in subpatterns followed
by one or more ellipses may occur only in subtemplates that are followed by
(at least) as many ellipses. These pattern variables are replaced in the output
by the input subforms to which they are bound, distributed as specified. If a
pattern variable is followed by more ellipses in the subtemplate than in
the associated subpattern, the input form is replicated as necessary. The
subtemplate must contain at least one pattern variable from a subpattern
followed by an ellipsis, and for at least one such pattern variable, the
subtemplate must be followed by exactly as many ellipses as the subpattern
in which the pattern variable appears.
[R6RS] Returns #t if obj is an identifier, i.e., a syntax object representing an identifier, and #f otherwise.
[R6RS] Id1 and id2 must be identifiers. The procedure
bound-identifier=?
returns #t if given arguments are exactly the same object.
The bound-identifier=? procedure can be used for detecting duplicate identifiers in a binding construct or for other preprocessing of a binding construct that requires detecting instances of the bound identifiers.
[R6RS] Id1 and id2 must be identifiers. The free-identifier=?
procedure returns #t if given arguments are indicating the same bindings.
[R6RS] Strips all syntactic information from a syntax object and returns the corresponding Scheme datum.
[R6RS] Template-id must be a template identifier and _datum_should be a datum value.
The datum->syntax
procedure returns a syntax-object representation of
datum that contains the same contextual information as template-id,
with the effect that the syntax object behaves as if it were introduced into the
code when template-id was introduced.
The datum->syntax
procedure allows a transformer to "bend" lexical scoping
rules by creating implicit identifiers that behave as if they were present in the
input form, thus permitting the definition of macros that introduce visible
bindings for or references to identifiers that do not appear explicitly in the
input form. For example, the following defines a loop
expression that uses
this controlled form of identifier capture to bind the variable break to an escape
procedure within the loop body.
(define-syntax loop
(lambda (x)
(syntax-case x ()
[(k e ...)
(with-syntax
([break (datum->syntax (syntax k) 'break)])
(syntax
(call-with-current-continuation
(lambda (break)
(let f () e ... (f))))))])))
(let ((n 3) (ls '()))
(loop
(if (= n 0) (break ls))
(set! ls (cons 'a ls))
(set! n (- n 1))))
(a a a)
[R6RS] L must be a list or syntax object representing a list-structured form. The number of temporaries generated is the number of elements in l. Each temporary is guaranteed to be unique.
NOTE: If you want to create just one temporary symbol and do not think about
portability, it's better to use gensym
in (sagittarius)
library.
[R6RS] The with-syntax
form is used to bind pattern variables, just
as let
is used to bind variables. This allows a transformer to construct
its output in separate pieces, then put the pieces together.
Each pattern is identical in form to a syntax-case
pattern. The
value of each expression is computed and destructured according to the
corresponding pattern, and pattern variables within the pattern are
bound as with syntax-case
to the corresponding portions of the value
within body.
[R6RS] The quasisyntax
form is similar to syntax
, but it
allows parts of the quoted text to be evaluated, in a manner similar to the
operation of quasiquote
.
Within a quasisyntax
template, subforms of unsyntax
and
unsyntax-splicing
forms are evaluated, and everything else is treated
as ordinary template material, as with syntax
. The value of each
unsyntax
subform is inserted into the output in place of the unsyntax
form, while the value of each unsyntax-splicing
subform is spliced into
the surrounding list or vector structure. Uses of unsyntax
and
unsyntax-splicing
are valid only within quasisyntax
expressions.
A quasisyntax
expression may be nested, with each quasisyntax
introducing a new level of syntax quotation and each unsyntax
or
unsyntax-splicing
taking away a level of quotation. An expression nested
within n quasisyntax
expressions must be within n unsyntax
or
unsyntax-splicing
expressions to be evaluated.
[R6RS] Who must be #f or a string or a symbol. Message must be a string. Form must be a syntax object or a datum value. Subform must be a syntax object or a datum value.
The syntax-violation
procedure raises an exception, reporting a syntax
violation. Who should describe the macro transformer that detected the
exception. The message argument should describe the violation. _Form_should be the erroneous source syntax object or a datum value representing a form.
The optional subform argument should be a syntax object or datum value
representing a form that more precisely locates the violation.