12.1 Pattern-Based Syntax Matching

► |  | The Racket Reference

1 | Language Model
2 | Notation for Documentation
3 | Syntactic Forms
4 | Datatypes
5 | Structures
6 | Classes and Objects
7 | Units
8 | Contracts
9 | Pattern Matching
10 | Control Flow
11 | Concurrency and Parallelism
12 | Macros
13 | Input and Output
14 | Reflection and Security
15 | Operating System
16 | Memory Management
17 | Unsafe Operations
18 | Running Racket
| Bibliography
| Index

▼ | 12 | Macros

12.1 | Pattern-Based Syntax Matching
12.2 | Syntax Object Content
12.3 | Syntax Object Bindings
12.4 | Syntax Transformers
12.5 | Syntax Parameters
12.6 | Local Binding with Splicing Body
12.7 | Syntax Object Properties
12.8 | Syntax Taints
12.9 | Expanding Top-Level Forms
12.10 | Serializing Syntax
12.11 | File Inclusion
12.12 | Syntax Utilities
12.13 | Phase and Space Utilities

On this page:

syntax-case
syntax-case*
with-syntax
syntax
~@
~?
quasisyntax
unsyntax
unsyntax-splicing
syntax/ loc
quasisyntax/ loc
quote-syntax/ prune
syntax-rules
syntax-id-rules
define-syntax-rule
...
_
syntax-pattern-variable?

top contents ← prev up next →

#### 12.1`` Pattern-Based Syntax Matching🔗ℹ

> > syntax
> > (syntax-case stx-expr (literal-id ...)
> > clause ...)
> clause |  | = |  | [pattern result-expr]
> |  | | |  | [pattern fender-expr result-expr]
> pattern |  | = |  | np-pattern
> |  | | |  | (pattern ...)
> |  | | |  | (pattern ...+ . np-pattern)
> |  | | |  | (pattern ... pattern ellipsis pattern ... . np-pattern)
> np-pattern |  | = |  | _
> |  | | |  | id
> |  | | |  | #(pattern ...)
> |  | | |  | #(pattern ... pattern ellipsis pattern ...)
> |  | | |  | #&pattern
> |  | | |  | #s(key-datum pattern ...)
> |  | | |  | #s(key-datum pattern ... pattern ellipsis pattern ...)
> |  | | |  | (ellipsis stat-pattern)
> |  | | |  | const
> stat-pattern |  | = |  | id
> |  | | |  | (stat-pattern ...)
> |  | | |  | (stat-pattern ...+ . stat-pattern)
> |  | | |  | #(stat-pattern ...)
> |  | | |  | #&stat-pattern
> |  | | |  | #s(key-datum stat-pattern ...)
> |  | | |  | const
> ellipsis |  | = |  | ...

Finds the first pattern that matches the syntax object produced by stx-expr, and for which the corresponding fender-expr (if any) produces a true value; the result is from the corresponding result-expr, which is in tail position for the syntax-case form. If no clause matches, then the exn:fail:syntax exception is raised; the exception is generated by calling raise-syntax-error with #f as the “name” argument, a string with a generic error message, and the result of stx-expr.

A syntax object matches a pattern as follows:

> > _

> A _ pattern (i.e., an identifier with the same binding as _ and not among the literal-ids) matches any syntax object.

> > id

> An id matches any syntax object when it is not bound to ... or _ and does not have the same binding as any literal-id. The id is further bound as pattern variable for the corresponding fender-expr (if any) and result-expr. A pattern-variable binding is a transformer binding; the pattern variable can be referenced only through forms like syntax. The binding’s value is the syntax object that matched the pattern with a depth marker of 0.

> With a stat-pattern, ... is not treated specially. It either matches a literal-id or is bound as a pattern variable.

> An id that has the same binding as a literal-id matches a syntax object that is an identifier with the same binding in the sense of free-identifier=?. The match does not introduce any pattern variables.

> > (pattern ...)

> A (pattern ...) pattern matches a syntax object whose datum form (i.e., without lexical information) is a list with as many elements as sub-patterns in the pattern, and where each syntax object that corresponds to an element of the list matches the corresponding sub-pattern.

> Any pattern variables bound by the sub-patterns are bound by the complete pattern; the bindings must all be distinct.

> > (pattern ...+ . np-pattern)

> Like the previous kind of pattern, but matches syntax objects that are not necessarily lists; for n sub-patterns before the final np-pattern, the syntax object’s datum must be a pair such that n-1 cdrs produce pairs. The final np-pattern is matched against the syntax object corresponding to the nth cdr (or the datum->syntax coercion of the datum using the nearest enclosing syntax object’s lexical context and source location).

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

> Like the (pattern ...) kind of pattern, but matching a syntax object with any number (zero or more) elements that match the sub-pattern followed by ellipsis in the corresponding position relative to other sub-patterns.

> For each pattern variable bound by the sub-pattern followed by ellipsis, the larger pattern binds the same pattern variable to a list of values, one for each element of the syntax object matched to the sub-pattern, with an incremented depth marker. (The sub-pattern itself may contain ellipsis, leading to a pattern variables bound to lists of lists of syntax objects with a depth marker of 2, and so on.)

> All patterns forms with ellipsis apply only when ellipsis is not among the literal-ids.

> > (pattern ... pattern ellipsis pattern ... . np-pattern)

> Like the previous kind of pattern, but with a final np-pattern as for (pattern ...+ . np-pattern). The final np-pattern never matches a syntax object whose datum is a pair.

> > #(pattern ...)

> Like a (pattern ...) pattern, but matching a vector syntax object whose elements match the corresponding sub-patterns.

> > #(pattern ... pattern ellipsis pattern ...)

> Like a (pattern ... pattern ellipsis pattern ...) pattern, but matching a vector syntax object whose elements match the corresponding sub-patterns.

> > #&pattern

> Matches a box syntax object whose content matches the pattern.

> > #s(key-datum pattern ...)

> Like a (pattern ...) pattern, but matching a prefab structure syntax object whose fields match the corresponding sub-patterns. The key-datum must correspond to a valid first argument to make-prefab-struct.

> > #s(key-datum pattern ... pattern ellipsis pattern ...)

> Like a (pattern ... pattern ellipsis pattern ...) pattern, but matching a prefab structure syntax object whose elements match the corresponding sub-patterns.

> > (ellipsis stat-pattern)

> Matches the same as stat-pattern, which is like a pattern, but identifiers with the binding ... are treated the same as other ids.

> > const

> A const is any datum that does not match one of the preceding forms; a syntax object matches a const pattern when its datum is equal? to the quoted const.

If stx-expr produces a non-syntax object, then its result is converted to a syntax object using datum->syntax and the lexical context and source location of the stx-expr.

If stx-expr produces a syntax object that is tainted, then any syntax object bound by a pattern are tainted.

Examples:

> > (require (for-syntax racket/base))
> > (define-syntax (swap stx)
> (syntax-case stx ()
> [(_ a b) #'(let ([t a])
> (set! a b)
> (set! b t))]))
> > (let ([x 5] [y 10])
> (swap x y)
> (list x y))
> '(10 5)
> > (syntax-case #'(ops 1 2 3 => +) (=>)
> [(_ x ... => op) #'(op x ...)])
> #<syntax:eval:682:0 (+ 1 2 3)>
> > (syntax-case #'(let ([x 5] [y 9] [z 12])
> (+ x y z))
> (let)
> [(let ([var expr] ...) body ...)
> (list #'(var ...)
> #'(expr ...))])
> '(#<syntax:eval:683:0 (x y z)> #<syntax:eval:683:0 (5 9 12)>)

> > syntax
> > (syntax-case* stx-expr (literal-id ...) id-compare-expr
> > clause ...)

Like syntax-case, but id-compare-expr must produce a procedure that accepts two arguments. A literal-id in a pattern matches an identifier for which the procedure returns true when given the identifier to match (as the first argument) and the identifier in the pattern (as the second argument).

In other words, syntax-case is like syntax-case* with an id-compare-expr that produces free-identifier=?.

> > syntax
> > (with-syntax ([pattern stx-expr] ...)
> > body ...+)

Similar to syntax-case, in that it matches a pattern to a syntax object. Unlike syntax-case, all patterns are matched, each to the result of a corresponding stx-expr, and the pattern variables from all matches (which must be distinct) are bound with a single body sequence. The result of the with-syntax form is the result of the last body, which is in tail position with respect to the with-syntax form.

If any pattern fails to match the corresponding stx-expr, the exn:fail:syntax exception is raised.

A with-syntax form is roughly equivalent to the following syntax-case form:

> (syntax-case (list stx-expr ...) ()
> [(pattern ...) (let () body ...+)])

However, if any individual stx-expr produces a non-syntax object, then it is converted to one using datum->syntax and the lexical context and source location of the individual stx-expr.

Examples:

> > (define-syntax (hello stx)
> (syntax-case stx ()
> [(_ name place)
> (with-syntax ([print-name #'(printf "~a\n" 'name)]
> [print-place #'(printf "~a\n" 'place)])
> #'(begin
> (define (name times)
> (printf "Hello\n")
> (for ([i (in-range 0 times)])
> print-name))
> (define (place times)
> (printf "From\n")
> (for ([i (in-range 0 times)])
> print-place))))]))
> > (hello jon utah)
> > (jon 2)
> Hello
> jon
> jon
> > (utah 2)
> From
> utah
> utah
> > (define-syntax (math stx)
> (define (make+1 expression)
> (with-syntax ([e expression])
> #'(+ e 1)))
> (syntax-case stx ()
> [(_ numbers ...)
> (with-syntax ([(added ...)
> (map make+1
> (syntax->list #'(numbers ...)))])
> #'(begin
> (printf "got ~a\n" added)
> ...))]))
> > (math 3 1 4 1 5 9)
> got 4
> got 2
> got 5
> got 2
> got 6
> got 10

> syntax (syntax template)
> template |  | = |  | id
> |  | | |  | (head-template ...)
> |  | | |  | (head-template ...+ . template)
> |  | | |  | #(head-template ...)
> |  | | |  | #&template
> |  | | |  | #s(key-datum head-template ...)
> |  | | |  | (~? template template)
> |  | | |  | (ellipsis stat-template)
> |  | | |  | const
> head-template |  | = |  | template
> |  | | |  | head-template ellipsis ...+
> |  | | |  | (~@ . template)
> |  | | |  | (~? head-template head-template)
> |  | | |  | (~? head-template)
> stat-template |  | = |  | like template, but without ..., ~?, and ~@
> ellipsis |  | = |  | ...

Constructs a syntax object based on a template, which can include pattern variables bound by syntax-case or with-syntax.

A template produces a single syntax object. A head-template produces a sequence of zero or more syntax objects. A stat-template is like a template, except that ..., ~?, and ~@ are interpreted as constants instead of template forms.

A template produces a syntax object as follows:

> > id

> If id is bound as a pattern variable, then id as a template produces the pattern variable’s match result. Unless the id is a sub-template that is replicated by ellipsis in a larger template, the pattern variable’s value must be a syntax object with a depth marker of 0 (as opposed to a list of matches).

> More generally, if the pattern variable’s value has a depth marker n, then it can only appear within a template where it is replicated by at least n ellipsises. In that case, the template will be replicated enough times to use each match result at least once.

> If id is not bound as a pattern variable, then id as a template produces (quote-syntax id).

> > (head-template ...)

> Produces a syntax object whose datum is a list, and where the elements of the list correspond to syntax objects produced by the head-templates.

> > (head-template ... . template)

> Like the previous form, but the result is not necessarily a list; instead, the place of the empty list in the resulting syntax object’s datum is taken by the syntax object produced by template.

> > #(head-template ...)

> Like the (head-template ...) form, but producing a syntax object whose datum is a vector instead of a list.

> > #&template

> Produces a syntax object whose datum is a box holding the syntax object produced by template.

> > #s(key-datum head-template ...)

> Like the (head-template ...) form, but producing a syntax object whose datum is a prefab structure instead of a list. The key-datum must correspond to a valid first argument of make-prefab-struct.

> > (~? template1 template2)

> Produces the result of template1 if template1 has no pattern variables with “missing values”; otherwise, produces the result of template2.

> A pattern variable bound by syntax-case never has a missing value, but pattern variables bound by syntax-parse (for example, ~or or ~optional patterns) can.

> Examples:

> > > (syntax-parse #'(m 1 2 3)
> > [(_ (~optional (~seq #:op op:expr)) arg:expr ...)
> > #'((~? op +) arg ...)])
> > #<syntax:eval:3:0 (+ 1 2 3)>
> > > (syntax-parse #'(m #:op max 1 2 3)
> > [(_ (~optional (~seq #:op op:expr)) arg:expr ...)
> > #'((~? op +) arg ...)])
> > #<syntax:eval:4:0 (max 1 2 3)>

> > (ellipsis stat-template)

> Produces the same result as stat-template, which is like a template, but ..., ~?, and ~@ are treated like an id (with no pattern binding).

> > const

> A const template is any form that does not match the preceding cases, and it produces the result (quote-syntax const).

A head-template produces a sequence of syntax objects; that sequence is “inlined” into the result of the enclosing template. The result of a head-template is defined as follows:

> > template

> Produces one syntax object, according to the rules for template above.

> > head-template ellipsis ...+

> Generates a sequence of syntax objects by “mapping” the head-template over the values of its pattern variables. The number of iterations depends on the values of the pattern variables referenced within the sub-template.

> To be more precise: Let outer be inner followed by one ellipsis. A pattern variable is an iteration pattern variable for outer if occurs at a depth equal to its depth marker. There must be at least one; otherwise, an error is raised. If there are multiple iteration variables, then all of their values must be lists of the same length. The result for outer is produced by mapping the inner template over the iteration pattern variable values and decreasing their effective depth markers by 1 within inner. The outer result is formed by appending the inner results.

> Consequently, if a pattern variable occurs at a depth greater than its depth marker, it is used as an iteration pattern variable for the innermost ellipses but not the outermost. A pattern variable must not occur at a depth less than its depth marker; otherwise, an error is raised.

> > syntax (~@ . template)

> Produces the sequence of elements in the syntax list produced by template. If template does not produce a proper syntax list, an exception is raised.

> Examples:

> > > (with-syntax ([(key ...) #'('a 'b 'c)]
> > [(val ...) #'(1 2 3)])
> > #'(hash (~@ key val) ...))
> > #<syntax:eval:2:0 (hash (quote a) 1 (quote b) 2 (quote c) 3)>
> > > (with-syntax ([xs #'(2 3 4)])
> > #'(list 1 (~@ . xs) 5))
> > #<syntax:eval:3:0 (list 1 2 3 4 5)>

> > syntax (~? head-template1 head-template2)

> Produces the result of head-template1 if none of its pattern variables have “missing values”; otherwise produces the result of head-template2.

> > (~? head-template)

> Produces the result of head-template if none of its pattern variables have “missing values”; otherwise produces nothing.

> Equivalent to (~? head-template (~@)).

A (syntax template) form is normally abbreviated as #'template; see also Reading Quotes. If template contains no pattern variables, then #'template is equivalent to (quote-syntax template).

Changed in version 6.90.0.25 of package base: Added ~@ and ~?.

> syntax (quasisyntax template)

Like syntax, but (unsyntax expr) and (unsyntax-splicing expr) escape to an expression within the template.

The expr must produce a syntax object (or syntax list) to be substituted in place of the unsyntax or unsyntax-splicing form within the quasiquoting template, just like unquote and unquote-splicing within quasiquote, except that a hash table value position is not an escape position for quasisyntax. (If the escaped expression does not generate a syntax object, it is converted to one in the same way as for the right-hand side of with-syntax.) Nested quasisyntaxes introduce quasiquoting layers in the same way as nested quasiquotes.

Also analogous to quasiquote, the reader converts #` to quasisyntax, #, to unsyntax, and #,@ to unsyntax-splicing. See also Reading Quotes.

> syntax (unsyntax expr)

Illegal as an expression form. The unsyntax form is for use only with a quasisyntax template.

> syntax (unsyntax-splicing expr)

Illegal as an expression form. The unsyntax-splicing form is for use only with a quasisyntax template.

> syntax (syntax/loc loc-expr template)
> | loc-expr |  | : |  |
> (or/c #f srcloc? syntax?
> (list/c any/c
> (or/c exact-positive-integer? #f)
> (or/c exact-nonnegative-integer? #f)
> (or/c exact-positive-integer? #f)
> (or/c exact-nonnegative-integer? #f))
> (vector/c any/c
> (or/c exact-positive-integer? #f)
> (or/c exact-nonnegative-integer? #f)
> (or/c exact-positive-integer? #f)
> (or/c exact-nonnegative-integer? #f)))

Like syntax, except that the immediate resulting syntax object takes its source-location information from the result of loc-expr.

Only the source location of the immediate result—the “outermost” syntax object—is adjusted. The source location is not adjusted if both the source and position of loc-expr are #f. The source location is adjusted only if the resulting syntax object comes from the template itself rather than the value of a syntax pattern variable. For example, if x is a syntax pattern variable, then (syntax/loc loc-expr x) does not use the location of loc-expr.

Changed in version 6.90.0.25 of package base: Previously, syntax/loc did not enforce the contract on loc-expr if template was just a pattern variable.
Changed in version 8.2.0.6: Allows loc-expr to be any source location value that datum->syntax accepts.

> syntax (quasisyntax/loc loc-expr template)
> | loc-expr |  | : |  |
> (or/c #f srcloc? syntax?
> (list/c any/c
> (or/c exact-positive-integer? #f)
> (or/c exact-nonnegative-integer? #f)
> (or/c exact-positive-integer? #f)
> (or/c exact-nonnegative-integer? #f))
> (vector/c any/c
> (or/c exact-positive-integer? #f)
> (or/c exact-nonnegative-integer? #f)
> (or/c exact-positive-integer? #f)
> (or/c exact-nonnegative-integer? #f)))

Like quasisyntax, but with source-location assignment like syntax/loc.

Changed in version 8.2.0.6 of package base: Allows loc-expr to be any source location value that datum->syntax accepts.

> syntax (quote-syntax/prune id)

Like quote-syntax, but the lexical context of id is pruned via identifier-prune-lexical-context to including binding only for the symbolic name of id and for '#%top. Use this form to quote an identifier when its lexical information will not be transferred to other syntax objects (except maybe to '#%top for a top-level binding).

> > syntax
> > (syntax-rules (literal-id ...)
> > [(id . pattern) template] ...)

Equivalent to

> (lambda (stx)
> (syntax-case stx (literal-id ...)
> [(generated-id . pattern) (syntax-protect #'template)] ...))

where each generated-id binds no identifier in the corresponding template. This in particular means that the id positions are ignored. Conventionally, the id positions should be the identifier _.

Examples:

> > (define-syntax my-let*
> (syntax-rules ()
> [(_ () body ...) (let () body ...)]
> [(_ ([x v] binding ...) body ...)
> (let ([x v])
> (my-let* (binding ...) body ...))]))
> > (my-let* ([x 42]
> [x (+ x 1)])
> x)
> 43

> > syntax
> > (syntax-id-rules (literal-id ...)
> > [pattern template] ...)

Equivalent to

> (make-set!-transformer
> (lambda (stx)
> (syntax-case stx (literal-id ...)
> [pattern (syntax-protect #'template)] ...)))

> syntax (define-syntax-rule (id . pattern) template)

Equivalent to

> (define-syntax id
> (syntax-rules ()
> [(id . pattern) template]))

but with syntax errors potentially phrased in terms of pattern.

> syntax ...

The ... transformer binding prohibits ... from being used as an expression. This binding is useful only in syntax patterns and templates (or other unrelated expression forms that treat it specially like ->), where it indicates repetitions of a pattern or template. See syntax-case and syntax.

> syntax _

The _ transformer binding prohibits _ from being used as an expression. This binding is useful only in syntax patterns, where it indicates a pattern that matches any syntax object. See syntax-case.

> syntax ~?
> syntax ~@

The ~? and ~@ transformer bindings prohibit these forms from being used as an expression. The bindings are useful only in syntax templates. See syntax.

Added in version 6.90.0.25 of package base.

> procedure (syntax-pattern-variable? v) → boolean?
> v : any/c

Returns #t if v is a value that, as a transformer-binding value, makes the bound variable as pattern variable in syntax and other forms. To check whether an identifier is a pattern variable, use syntax-local-value to get the identifier’s transformer value, and then test the value with syntax-pattern-variable?.

The syntax-pattern-variable? procedure is provided for-syntax by racket/base.

top contents ← prev up next →