{"size": 22966, "ext": "scrbl", "max_stars_repo_path": "pkgs/racket-doc/scribblings/reference/stx-patterns.scrbl", "max_stars_repo_name": "lkh01/racket", "max_stars_repo_stars_event_min_datetime": "2018-07-05T21:18:24.000Z", "max_stars_repo_stars_event_max_datetime": "2021-06-04T14:48:37.000Z", "max_issues_repo_path": "pkgs/racket-doc/scribblings/reference/stx-patterns.scrbl", "max_issues_repo_name": "lkh01/racket", "max_issues_repo_issues_event_min_datetime": "2017-05-10T07:33:20.000Z", "max_issues_repo_issues_event_max_datetime": "2018-07-19T15:49:46.000Z", "max_forks_repo_path": "pkgs/racket-doc/scribblings/reference/stx-patterns.scrbl", "max_forks_repo_name": "lkh01/racket", "max_forks_repo_forks_event_min_datetime": "2016-04-25T11:47:57.000Z", "max_forks_repo_forks_event_max_datetime": "2017-05-09T14:52:48.000Z"}
{"max_stars_count": 4, "max_issues_count": 9, "max_forks_count": 3, "avg_line_length": 38.2129783694, "max_line_length": 101, "alphanum_fraction": 0.6750413655}
#lang scribble/doc
@(require "mz.rkt" (for-label syntax/parse))

@(define lit-ellipsis (racket ...))

@(define syntax-eval
   (lambda ()
     (let ([the-eval (make-base-eval)])
       (the-eval '(require (for-syntax racket/base)))
       the-eval)))

@title[#:tag "stx-patterns"]{Pattern-Based Syntax Matching}

@defform/subs[#:literals (_)
              (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
                          (code:line #,(tt "#")(pattern ...))
                          (code:line #,(tt "#")(pattern ... pattern ellipsis pattern ...))
                          (code:line #,(tt "#&")pattern)
                          (code:line #,(tt "#s")(key-datum pattern ...))
                          (code:line #,(tt "#s")(key-datum pattern ... pattern ellipsis pattern ...))
                          (ellipsis stat-pattern)
                          const]
               [stat-pattern id
                             (stat-pattern ...)
                             (stat-pattern ...+ . stat-pattern)
                             (code:line #,(tt "#")(stat-pattern ...))
                             const]
               [ellipsis #,lit-ellipsis])]{

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

A syntax object matches a @racket[pattern] as follows:

 @specsubform[_]{

 A @racket[_] pattern (i.e., an identifier with the same binding as
 @racket[_]) matches any syntax object.}

 @specsubform[id]{

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

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

 @specsubform[(pattern ...)]{

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

 Any @tech{pattern variables} bound by the sub-@racket[pattern]s are
 bound by the complete pattern; the bindings must all be distinct.}

 @specsubform[(pattern ...+ . np-pattern)]{

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

 @specsubform[(pattern ... pattern ellipsis pattern ...)]{

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

 For each pattern variable bound by the sub-@racket[pattern] followed
 by @racket[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-@racket[pattern], with an incremented
 @tech{depth marker}. (The sub-@racket[pattern] itself may contain
 @racket[ellipsis], leading to a pattern variables bound to lists of
 lists of syntax objects with a @tech{depth marker} of @math{2}, and
 so on.)}

 @specsubform[(pattern ... pattern ellipsis pattern ... . np-pattern)]{

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

 @specsubform[(code:line #,(tt "#")(pattern ...))]{

 Like a @racket[(pattern ...)] pattern, but matching a vector syntax object
 whose elements match the corresponding sub-@racket[pattern]s.}

 @specsubform[(code:line #,(tt "#")(pattern ... pattern ellipsis pattern ...))]{

 Like a @racket[(pattern ... pattern ellipsis pattern ...)] pattern,
 but matching a vector syntax object whose elements match the
 corresponding sub-@racket[pattern]s.}

 @specsubform[(code:line #,(tt "#&")pattern)]{

 Matches a box syntax object whose content matches the
 @racket[pattern].}

 @specsubform[(code:line #,(tt "#s")(key-datum pattern ...))]{

 Like a @racket[(pattern ...)] pattern, but matching a @tech{prefab}
 structure syntax object whose fields match the corresponding
 sub-@racket[pattern]s. The @racket[key-datum] must correspond to a
 valid first argument to @racket[make-prefab-struct].}

 @specsubform[(code:line #,(tt "#s")(key-datum pattern ... pattern ellipsis pattern ...))]{

 Like a @racket[(pattern ... pattern ellipsis pattern ...)] pattern,
 but matching a @tech{prefab} structure syntax object whose elements
 match the corresponding sub-@racket[pattern]s.}

 @specsubform[(ellipsis stat-pattern)]{

 Matches the same as @racket[stat-pattern], which is like a @racket[pattern],
 but identifiers with the binding @racket[...] are treated the same as
 other @racket[id]s.}

 @specsubform[const]{

 A @racket[const] is any datum that does not match one of the
 preceding forms; a syntax object matches a @racket[const] pattern
 when its datum is @racket[equal?] to the @racket[quote]d
 @racket[const].}

If @racket[stx-expr] produces a non-@tech{syntax object}, then its
result is converted to a syntax object using @racket[datum->syntax]
and the lexical context and source location of the @racket[stx-expr].

If @racket[stx-expr] produces a syntax object that is @tech{tainted}
or @tech{armed}, then any syntax object bound by a @racket[pattern]
are @tech{tainted}---unless the binding corresponds to the whole
syntax object produced by @racket[stx-expr], in which case it remains
@tech{tainted} or @tech{armed}.

@mz-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))

(syntax-case #'(ops 1 2 3 => +) (=>)
  [(_ x ... => op) #'(op x ...)])

(syntax-case #'(let ([x 5] [y 9] [z 12])
                 (+ x y z))
             (let)
  [(let ([var expr] ...) body ...)
   (list #'(var ...)
         #'(expr ...))])
]}

@defform[(syntax-case* stx-expr (literal-id ...) id-compare-expr
           clause ...)]{

Like @racket[syntax-case], but @racket[id-compare-expr] must produce a
procedure that accepts two arguments. A @racket[literal-id] in a
@racket[_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 @racket[_pattern] (as the second argument).

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


@defform[(with-syntax ([pattern stx-expr] ...)
           body ...+)]{

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

If any @racket[pattern] fails to match the corresponding
@racket[stx-expr], the @exnraise[exn:fail:syntax].

A @racket[with-syntax] form is roughly equivalent to the following
@racket[syntax-case] form:

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

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

@examples[#:eval (syntax-eval)
(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)
(utah 2)

(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)
]}

@defform[#:literals (~? ~@) (syntax template)
         #:grammar
         ([template id
                    (head-template ...)
                    (head-template ...+ . template)
                    (code:line #,(tt "#")(head-template ...))
                    (code:line #,(tt "#&")template)
                    (code:line #,(tt "#s")(key-datum head-template ...))
                    (~? template template)
                    (ellipsis stat-template)
                    const]
          [head-template template
                         (code:line head-template ellipsis ...+)
                         (~@ . template)
                         (~? head-template head-template)
                         (~? head-template)]
          [stat-template @#,elem{like @svar{template}, but without @|lit-ellipsis|,
                                 @racket[~?], and @racket[~@]}]
          [ellipsis #,lit-ellipsis])]{

Constructs a syntax object based on a @racket[template], which can
include @tech{pattern variables} bound by @racket[syntax-case] or
@racket[with-syntax].

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

A @svar[template] produces a syntax object as follows:

 @specsubform[id]{

 If @racket[id] is bound as a @tech{pattern variable}, then
 @racket[id] as a template produces the @tech{pattern variable}'s
 match result. Unless the @racket[id] is a sub-@racket[template] that is
 replicated by @racket[ellipsis] in a larger @racket[template], the
 @tech{pattern variable}'s value must be a syntax object with a
 @tech{depth marker} of @math{0} (as opposed to a list of
 matches).

 More generally, if the @tech{pattern variable}'s value has a depth
 marker @math{n}, then it can only appear within a template where it
 is replicated by at least @math{n} @racket[ellipsis]es. In that case,
 the template will be replicated enough times to use each match result
 at least once.

 If @racket[id] is not bound as a pattern variable, then @racket[id]
 as a template produces @racket[(quote-syntax id)].}

 @specsubform[(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
 @racket[head-template]s.}

 @specsubform[(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 @racket[template].}

 @specsubform[(code:line #,(tt "#")(head-template ...))]{

   Like the @racket[(head-template ...)] form, but producing a syntax
   object whose datum is a vector instead of a list.}

 @specsubform[(code:line #,(tt "#&")template)]{

   Produces a syntax object whose datum is a box holding the
   syntax object produced by @racket[template].}

 @specsubform[(code:line #,(tt "#s")(key-datum head-template ...))]{

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

 @specsubform[#:literals (~?) (~? template1 template2)]{

   Produces the result of @racket[template1] if @racket[template1] has no
   pattern variables with ``missing values''; otherwise, produces the result of
   @racket[template2].

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

   @examples[#:eval (let ([ev (syntax-eval)]) (ev '(require syntax/parse/pre)) ev)
   (syntax-parse #'(m 1 2 3)
     [(_ (~optional (~seq #:op op:expr)) arg:expr ...)
      #'((~? op +) arg ...)])
   (syntax-parse #'(m #:op max 1 2 3)
     [(_ (~optional (~seq #:op op:expr)) arg:expr ...)
      #'((~? op +) arg ...)])
   ]}

 @specsubform[(ellipsis stat-template)]{

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

 @specsubform[const]{

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

A @racket[head-template] produces a sequence of syntax objects; that sequence is
``inlined'' into the result of the enclosing @racket[template]. The result of a
@racket[head-template] is defined as follows:

 @specsubform[template]{

   Produces one syntax object, according to the rules for @svar[template]
   above.}

 @specsubform[(code:line head-template ellipsis ...+)]{

  Generates a sequence of syntax objects by ``@racket[map]ping'' the
  @racket[head-template] over the values of its pattern variables. The number of
  iterations depends on the values of the @tech{pattern variables} referenced
  within the sub-template.

  To be more precise: Let @racket[_outer] be @racket[_inner] followed by one
  ellipsis. A @tech{pattern variable} is an @deftech{iteration pattern variable}
  for @racket[_outer] if occurs at a depth equal to its @tech{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 @racket[_outer] is produced by
  @racket[map]ping the @racket[_inner] template over the @tech{iteration pattern
  variable} values and decreasing their effective @tech{depth markers} by 1
  within @racket[_inner]. The @racket[_outer] result is formed by appending the
  @racket[_inner] results.

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

 @specsubform[#:literals (~@) (~@ . template)]{

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

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

 @specsubform[#:literals (~?) (~? head-template1 head-template2)]{

   Produces the result of @racket[head-template1] if none of its pattern
   variables have ``missing values''; otherwise produces the result of
   @racket[head-template2]. }

 @specsubform[#:literals (~?) (~? head-template)]{

   Produces the result of @racket[head-template] if none of its pattern
   variables have ``missing values''; otherwise produces nothing.

   Equivalent to @racket[(~? head-template (~@))]. }

A @racket[(#,(racketkeywordfont "syntax") template)] form is normally
abbreviated as @racket[#'template]; see also
@secref["parse-quote"]. If @racket[template] contains no pattern
variables, then @racket[#'template] is equivalent to
@racket[(quote-syntax template)].

@history[#:changed "6.90.0.25" @elem{Added @racket[~@] and @racket[~?].}]
}


@defform[(quasisyntax template)]{

Like @racket[syntax], but @racket[(#,(racketkeywordfont "unsyntax")
_expr)] and @racket[(#,(racketkeywordfont "unsyntax-splicing") _expr)]
escape to an expression within the @racket[template].

The @racket[_expr] must produce a syntax object (or syntax list) to be
substituted in place of the @racket[unsyntax] or
@racket[unsyntax-splicing] form within the quasiquoting template, just
like @racket[unquote] and @racket[unquote-splicing] within
@racket[quasiquote]. (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 @racket[with-syntax].)  Nested
@racket[quasisyntax]es introduce quasiquoting layers in the same way
as nested @racket[quasiquote]s.

Also analogous to @racket[quasiquote], the reader converts @litchar{#`}
to @racket[quasisyntax], @litchar{#,} to @racket[unsyntax], and
@litchar["#,@"] to @racket[unsyntax-splicing]. See also
@secref["parse-quote"].}



@defform[(unsyntax expr)]{

Illegal as an expression form. The @racket[unsyntax] form is for use
only with a @racket[quasisyntax] template.}


@defform[(unsyntax-splicing expr)]{

Illegal as an expression form. The @racket[unsyntax-splicing] form is
for use only with a @racket[quasisyntax] template.}


@defform[(syntax/loc stx-expr template)
         #:contracts ([stx-expr syntax?])]{

Like @racket[syntax], except that the immediate resulting syntax
object takes its source-location information from the result of
@racket[stx-expr] (which must produce a syntax object).

Only the source location of the immediate result---the ``outermost''
syntax object---is adjusted. The source location is @emph{not}
adjusted if both the source and position of @racket[stx-expr] are
@racket[#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 @racket[_x] is a syntax
pattern variable, then @racket[(syntax/loc stx-expr _x)] does not use
the location of @racket[stx-expr].

@history[#:changed "6.90.0.25" @elem{Previously, @racket[syntax/loc]
did not enforce the contract on @racket[stx-expr] if @racket[template]
was just a pattern variable.}]}

@defform[(quasisyntax/loc stx-expr template)
         #:contracts ([stx-expr syntax?])]{

Like @racket[quasisyntax], but with source-location assignment like
@racket[syntax/loc].}


@defform[(quote-syntax/prune id)]{

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


@defform[(syntax-rules (literal-id ...)
           [(id . pattern) template] ...)]{

Equivalent to

@racketblock/form[
(lambda (stx)
  (syntax-case stx (literal-id ...)
    [(_generated-id . pattern) (syntax-protect (syntax template))] ...))
]

where each @racket[_generated-id] binds no identifier in the
corresponding @racket[template].}


@defform[(syntax-id-rules (literal-id ...)
           [pattern template] ...)]{

Equivalent to

@racketblock[
(make-set!-transformer
 (lambda (stx)
   (syntax-case stx (literal-id ...)
     [pattern (syntax-protect (syntax template))] ...)))
]}


@defform[(define-syntax-rule (id . pattern) template)]{

Equivalent to

@racketblock/form[
(define-syntax id
  (syntax-rules ()
   [(id . pattern) template]))
]

but with syntax errors potentially phrased in terms of 
@racket[pattern].}


@defidform[...]{

The @racket[...] transformer binding prohibits @racket[...] 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 @racket[->]), where it indicates repetitions
of a pattern or template. See @racket[syntax-case] and @racket[syntax].}

@defidform[_]{

The @racket[_] transformer binding prohibits @racket[_] 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
@racket[syntax-case].}

@deftogether[[
@defidform[~?]
@defidform[~@]
]]{

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

@history[#:added "6.90.0.25"]}

@defproc[(syntax-pattern-variable? [v any/c]) boolean?]{

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

The @racket[syntax-pattern-variable?] procedure is provided
@racket[for-syntax] by @racketmodname[racket/base].}
