racket/collects/scribblings/reference/match.scrbl
Sam Tobin-Hochstadt 40d2fd65b0 Add OrderedAnd patterns, and use them in ? patterns.
This guarantees that patterns like (? pred pat) will
always check `pred` before matching any of `pat`.
However, `and` patterns are not required to match left-
to-right.
2013-01-22 14:59:41 -05:00

667 lines
22 KiB
Racket

#lang scribble/doc
@(require "mz.rkt" "match-grammar.rkt" racket/match)
@(define match-eval (make-base-eval))
@(interaction-eval #:eval match-eval (require racket/match))
@(interaction-eval #:eval match-eval (require (for-syntax racket/base)))
@title[#:tag "match"]{Pattern Matching}
@guideintro["match"]{pattern matching}
The @racket[match] form and related forms support general pattern
matching on Racket values. See also @secref["regexp"] for information
on regular-expression matching on strings, bytes, and streams.
@note-lib[racket/match #:use-sources (racket/match)]
@defform/subs[(match val-expr clause ...)
([clause [pat body ...+]
[pat (=> id) body ...+]])]{
Finds the first @racket[pat] that matches the result of
@racket[val-expr], and evaluates the corresponding @racket[body]s with
bindings introduced by @racket[pat] (if any). The last @racket[body]
in the matching clause is evaluated in tail position with respect to
the @racket[match] expression.
To find a match, the @racket[clause]s are tried in order. If no
@racket[clause] matches, then the @exnraise[exn:misc:match?].
An optional @racket[(=> id)] between a @racket[pat] and the
@racket[body]s is bound to a @defterm{failure procedure} of zero
arguments. If this procedure is invoked, it escapes back to the
pattern matching expression, and resumes the matching process as if
the pattern had failed to match. The @racket[body]s must not mutate
the object being matched before calling the failure procedure,
otherwise the behavior of matching is unpredictable.
The grammar of @racket[pat] is as follows, where non-italicized
identifiers are recognized symbolically (i.e., not by binding).
@|match-grammar|
In more detail, patterns match as follows:
@itemize[
@item{@racket[_id] (excluding the reserved names @racketidfont{_},
@racketidfont{...}, @racketidfont{.._},
@racketidfont{..}@racket[_k], and
@racketidfont{..}@racket[_k] for non-negative integers
@racket[_k]) or @racket[(var _id)] --- matches anything, and binds @racket[id] to the
matching values. If an @racket[_id] is used multiple times
within a pattern, the corresponding matches must be the same
according to @racket[(match-equality-test)], except that
instances of an @racket[_id] in different @racketidfont{or} and
@racketidfont{not} sub-patterns are independent.
@examples[
#:eval match-eval
(match '(1 2 3)
[(list a b a) (list a b)]
[(list a b c) (list c b a)])
(match '(1 (x y z) 1)
[(list a b a) (list a b)]
[(list a b c) (list c b a)])
]}
@item{@racketidfont{_} --- matches anything, without binding any
identifiers.
@examples[
#:eval match-eval
(match '(1 2 3)
[(list _ _ a) a])
]}
@item{@racket[#t], @racket[#f], @racket[_string], @racket[_bytes],
@racket[_number], @racket[_char], or @racket[(#,(racketidfont
"quote") _datum)] --- matches an @racket[equal?] constant.
@examples[
#:eval match-eval
(match "yes"
["no" #f]
["yes" #t])
]}
@item{@racket[(#,(racketidfont "list") _lvp ...)] --- matches a list
of elements. In the case of @racket[(#,(racketidfont "list")
_pat ...)], the pattern matches a list with as many element as
@racket[_pat]s, and each element must match the corresponding
@racket[_pat]. In the more general case, each @racket[_lvp]
corresponds to a ``spliced'' list of greedy matches.
For spliced lists, @racketidfont{...} and @racketidfont{___}
are aliases for zero or more matches. The
@racketidfont{..}@racket[_k] and @racketidfont{__}@racket[_k]
forms are also aliases, specifying @racket[_k] or more
matches. Pattern variables that precede these splicing
operators are bound to lists of matching forms.
@examples[
#:eval match-eval
(match '(1 2 3)
[(list a b c) (list c b a)])
(match '(1 2 3)
[(list 1 a ...) a])
(match '(1 2 3)
[(list 1 a ..3) a]
[_ 'else])
(match '(1 2 3 4)
[(list 1 a ..3) a]
[_ 'else])
(match '(1 2 3 4 5)
[(list 1 a ..3 5) a]
[_ 'else])
(match '(1 (2) (2) (2) 5)
[(list 1 (list a) ..3 5) a]
[_ 'else])
]}
@item{@racket[(#,(racketidfont "list-rest") _lvp ... _pat)] ---
similar to a @racketidfont{list} pattern, but the final
@racket[_pat] matches the ``rest'' of the list after the last
@racket[_lvp]. In fact, the matched value can be a non-list
chain of pairs (i.e., an ``improper list'') if @racket[_pat]
matches non-list values.
@examples[
#:eval match-eval
(match '(1 2 3 . 4)
[(list-rest a b c d) d])
(match '(1 2 3 . 4)
[(list-rest a ... d) (list a d)])
]}
@item{@racket[(#,(racketidfont "list-no-order") _pat ...)] ---
similar to a @racketidfont{list} pattern, but the elements to
match each @racket[_pat] can appear in the list in any order.
@examples[
#:eval match-eval
(match '(1 2 3)
[(list-no-order 3 2 x) x])
]}
@item{@racket[(#,(racketidfont "list-no-order") _pat ... _lvp)] ---
generalizes @racketidfont{list-no-order} to allow a pattern
that matches multiple list elements that are interspersed in
any order with matches for the other patterns.
@examples[
#:eval match-eval
(match '(1 2 3 4 5 6)
[(list-no-order 6 2 y ...) y])
]}
@item{@racket[(#,(racketidfont "vector") _lvp ...)] --- like a
@racketidfont{list} pattern, but matching a vector.
@examples[
#:eval match-eval
(match #(1 (2) (2) (2) 5)
[(vector 1 (list a) ..3 5) a])
]}
@item{@racket[(#,(racketidfont "hash-table") (_pat _pat) ...)] ---
similar to @racketidfont{list-no-order}, but matching against
hash table's key--value pairs.
@examples[
#:eval match-eval
(match #hash(("a" . 1) ("b" . 2))
[(hash-table ("b" b) ("a" a)) (list b a)])
]}
@item{@racket[(#,(racketidfont "hash-table") (_pat _pat) ...+ _ooo)]
--- Generalizes @racketidfont{hash-table} to support a final
repeating pattern.
@examples[
#:eval match-eval
(match #hash(("a" . 1) ("b" . 2))
[(hash-table (key val) ...) key])
]}
@item{@racket[(#,(racketidfont "cons") _pat1 _pat2)] --- matches a pair value.
@examples[
#:eval match-eval
(match (cons 1 2)
[(cons a b) (+ a b)])
]}
@item{@racket[(#,(racketidfont "mcons") _pat1 _pat2)] --- matches a mutable pair value.
@examples[
#:eval match-eval
(match (mcons 1 2)
[(cons a b) 'immutable]
[(mcons a b) 'mutable])
]}
@item{@racket[(#,(racketidfont "box") _pat)] --- matches a boxed value.
@examples[
#:eval match-eval
(match #&1
[(box a) a])
]}
@item{@racket[(_struct-id _pat ...)] or
@racket[(#,(racketidfont "struct") _struct-id (_pat ...))] ---
matches an instance of a structure type named
@racket[_struct-id], where each field in the instance matches
the corresponding @racket[_pat]. See also @racket[struct*].
Usually, @racket[_struct-id] is defined with
@racket[struct]. More generally, @racket[_struct-id]
must be bound to expansion-time information for a structure
type (see @secref["structinfo"]), where the information
includes at least a predicate binding and field accessor
bindings corresponding to the number of field
@racket[_pat]s. In particular, a module import or a
@racket[unit] import with a signature containing a
@racket[struct] declaration can provide the structure type
information.
@defexamples[
#:eval match-eval
(define-struct tree (val left right))
(match (make-tree 0 (make-tree 1 #f #f) #f)
[(tree a (tree b _ _) _) (list a b)])
]}
@item{@racket[(#,(racketidfont "struct") _struct-id _)] ---
matches any instance of @racket[_struct-id], without regard to
contents of the fields of the instance.
}
@item{@racket[(#,(racketidfont "regexp") _rx-expr)] --- matches a
string that matches the regexp pattern produced by
@racket[_rx-expr]; see @secref["regexp"] for more information
about regexps.
@examples[
#:eval match-eval
(match "apple"
[(regexp #rx"p+") 'yes]
[_ 'no])
(match "banana"
[(regexp #rx"p+") 'yes]
[_ 'no])
]}
@item{@racket[(#,(racketidfont "regexp") _rx-expr _pat)] --- extends
the @racketidfont{regexp} form to further constrain the match
where the result of @racket[regexp-match] is matched against
@racket[_pat].
@examples[
#:eval match-eval
(match "apple"
[(regexp #rx"p+(.)" (list _ "l")) 'yes]
[_ 'no])
(match "append"
[(regexp #rx"p+(.)" (list _ "l")) 'yes]
[_ 'no])
]}
@item{@racket[(#,(racketidfont "pregexp") _rx-expr)] or
@racket[(#,(racketidfont "regexp") _rx-expr _pat)] --- like the
@racketidfont{regexp} patterns, but if @racket[_rx-expr]
produces a string, it is converted to a pattern using
@racket[pregexp] instead of @racket[regexp].}
@item{@racket[(#,(racketidfont "and") _pat ...)] --- matches if all
of the @racket[_pat]s match. This pattern is often used as
@racket[(#,(racketidfont "and") _id _pat)] to bind @racket[_id]
to the entire value that matches @racket[pat].
@examples[
#:eval match-eval
(match '(1 (2 3) 4)
[(list _ (and a (list _ ...)) _) a])
]}
@item{@racket[(#,(racketidfont "or") _pat ...)] --- matches if any of
the @racket[_pat]s match. @bold{Beware}: the result expression
can be duplicated once for each @racket[_pat]! Identifiers in
@racket[_pat] are bound only in the corresponding copy of the
result expression; in a module context, if the result
expression refers to a binding, then all @racket[_pat]s
must include the binding.
@examples[
#:eval match-eval
(match '(1 2)
[(or (list a 1) (list a 2)) a])
]}
@item{@racket[(#,(racketidfont "not") _pat ...)] --- matches when
none of the @racket[_pat]s match, and binds no identifiers.
@examples[
#:eval match-eval
(match '(1 2 3)
[(list (not 4) ...) 'yes]
[_ 'no])
(match '(1 4 3)
[(list (not 4) ...) 'yes]
[_ 'no])
]}
@item{@racket[(#,(racketidfont "app") _expr _pat)] --- applies
@racket[_expr] to the value to be matched; the result of the
application is matched against @racket[_pat].
@examples[
#:eval match-eval
(match '(1 2)
[(app length 2) 'yes])
]}
@item{@racket[(#,(racketidfont "?") _expr _pat ...)] --- applies
@racket[_expr] to the value to be matched, and checks whether
the result is a true value; the additional @racket[_pat]s must
also match; i.e., @racketidfont{?} combines a predicate
application and an @racketidfont{and} pattern. However,
@racketidfont{?}, unlike @racketidfont{and}, guarantees that
@racket[_expr] is matched before any of the @racket[_pat]s.
@examples[
#:eval match-eval
(match '(1 3 5)
[(list (? odd?) ...) 'yes])
]}
@item{@racket[(#,(racketidfont "quasiquote") _qp)] --- introduces a
quasipattern, in which identifiers match symbols. Like the
@racket[quasiquote] expression form, @racketidfont{unquote}
and @racketidfont{unquote-splicing} escape back to normal
patterns.
@examples[
#:eval match-eval
(match '(1 2 3)
[`(1 ,a ,(? odd? b)) (list a b)])
]}
@item{@racket[_derived-pattern] --- matches a pattern defined by a
macro extension via @racket[define-match-expander].}
]
Note that the matching process may destructure the input multiple times, and
may evaluate expressions embedded in patterns such as @racket[(#,(racketidfont
"app") expr pat)] in arbitrary order, or multiple times. Therefore, such
expressions must be safe to call multiple times, or in an order other than they
appear in the original program.
}
@; ----------------------------------------------------------------------
@section{Additional Matching Forms}
@defform/subs[(match* (val-expr ...+) clause* ...)
([clause* [(pat ...+) body ...+]
[(pat ...+) (=> id) body ...+]])]{
Matches a sequence of values against each clause in order, matching
only when all patterns in a clause match. Each clause must have the
same number of patterns as the number of @racket[val-expr]s.
@examples[#:eval match-eval
(match* (1 2 3)
[(_ (? number?) x) (add1 x)])
]
}
@defform[(match/values expr clause clause ...)]{
If @racket[expr] evaluates to @racket[n] values, then match all @racket[n]
values against the patterns in @racket[clause ...]. Each clause must contain
exactly @racket[n] patterns. At least one clause is required to determine how
many values to expect from @racket[expr].
}
@defform/subs[
(define/match (head args)
match*-clause ...)
([head id (head args)]
[args (code:line arg ...)
(code:line arg ... @#,racketparenfont{.} rest-id)]
[arg arg-id
[arg-id default-expr]
(code:line keyword arg-id)
(code:line keyword [arg-id default-expr])]
[match*-clause [(pat ...+) body ...+]
[(pat ...+) (=> id) body ...+]])
]{
Binds @racket[id] to a procedure that is defined by pattern matching
clauses using @racket[match*]. Each clause takes a sequence of
patterns that correspond to the arguments in the function header.
The arguments are ordered as they appear in the function header for
matching purposes.
The function header may contain optional or keyword arguments, or
may be in curried form.
@defexamples[#:eval match-eval
(define/match (fact n)
[(0) 1]
[(n) (* n (fact (sub1 n)))])
(fact 5)
(define/match ((f x) #:y [y '(1 2 3)])
[((regexp #rx"p+") `(,a 2 3)) a]
[(_ _) #f])
((f "ape") #:y '(5 2 3))
((f "dog"))
(define/match (g x y . rst)
[(0 0 '()) #t]
[(5 5 '(5 5)) #t]
[(_ _ _) #f])
(g 0 0)
(g 5 5 5 5)
(g 1 2)
]
}
@defform[(match-lambda clause ...)]{
Equivalent to @racket[(lambda (id) (match id clause ...))].
}
@defform[(match-lambda* clause ...)]{
Equivalent to @racket[(lambda lst (match lst clause ...))].
}
@defform[(match-lambda** clause* ...)]{
Equivalent to @racket[(lambda (args ...) (match* (args ...) clause* ...))],
where the number of @racket[args ...] is computed from the number of patterns
appearing in each of the @racket[clause*].
}
@defform[(match-let ([pat expr] ...) body ...+)]{
Generalizes @racket[let] to support pattern bindings. Each
@racket[expr] is matched against its corresponding @racket[pat] (the
match must succeed), and the bindings that @racket[pat] introduces are
visible in the @racket[body]s.
@examples[
#:eval match-eval
(match-let ([(list a b) '(1 2)]
[(vector x ...) #(1 2 3 4)])
(list b a x))
]}
@defform[(match-let* ([pat expr] ...) body ...+)]{
Like @racket[match-let], but generalizes @racket[let*], so that the
bindings of each @racket[pat] are available in each subsequent
@racket[expr].
@examples[
#:eval match-eval
(match-let* ([(list a b) '(#(1 2 3 4) 2)]
[(vector x ...) a])
x)
]}
@defform[(match-let-values ([(pat ...) expr] ...) body ...+)]{
Like @racket[match-let], but generalizes @racket[let-values].}
@defform[(match-let*-values ([(pat ...) expr] ...) body ...+)]{
Like @racket[match-let*], but generalizes @racket[let*-values].}
@defform[(match-letrec ([pat expr] ...) body ...+)]{
Like @racket[match-let], but generalizes @racket[letrec].}
@defform[(match-define pat expr)]{
Defines the names bound by @racket[pat] to the values produced by
matching against the result of @racket[expr].
@examples[
#:eval match-eval
(match-define (list a b) '(1 2))
b
]}
@defform[(match-define-values (pat pats ...) expr)]{
Like @racket[match-define] but for when expr produces multiple values.
Like match/values, it requires at least one pattern to determine the
number of values to expect.
@examples[
#:eval match-eval
(match-define-values (a b) (values 1 2))
b
]}
@; ----------------------------------------
@defproc[(exn:misc:match? [v any/c]) boolean?]{
A predicate for the exception raised in the case of a match failure.
}
@; ----------------------------------------
@section{Extending @racket[match]}
@defform*[((define-match-expander id proc-expr)
(define-match-expander id proc-expr proc-expr))]{
Binds @racket[id] to a @deftech{match expander}.
The first @racket[proc-expr] sub-expression must evaluate to a
transformer that produces a @racket[_pat] for @racket[match].
Whenever @racket[id] appears as the beginning of a pattern, this
transformer is given, at expansion time, a syntax object
corresponding to the entire pattern (including @racket[id]). The
pattern is replaced with the result of the transformer.
A transformer produced by a second @racket[proc-expr] sub-expression is
used when @racket[id] is used in an expression context. Using the
second @racket[proc-expr], @racket[id] can be given meaning both
inside and outside patterns.
For example, to extend the pattern matcher and destructure syntax lists,
@defs+int[
#:eval match-eval
((define-match-expander syntax-list
(lambda (stx)
(syntax-case stx ()
[(_ elts ...)
#'(? (lambda (x) (and (syntax? x)
(list? (syntax->list x))))
(app syntax->list (list elts ...)))])))
(define (make-keyword-predicate keyword)
(lambda (stx)
(and (identifier? stx)
(free-identifier=? stx keyword))))
(define or-keyword? (make-keyword-predicate #'or))
(define and-keyword? (make-keyword-predicate #'and))
)
(match #'(or 3 4)
[(syntax-list (? or-keyword?) b c)
(list "OOORRR!" b c)]
[(syntax-list (? and-keyword?) b c)
(list "AAANND!" b c)])
(match #'(and 5 6)
[(syntax-list (? or-keyword?) b c)
(list "OOORRR!" b c)]
[(syntax-list (? and-keyword?) b c)
(list "AAANND!" b c)])
]
}
@defthing[prop:match-expander struct-type-property?]{
A @tech{structure type property} to identify structure types that act
as @tech{match expanders} like the ones created by
@racket[define-match-expander].
The property value must be an exact non-negative integer or a
procedure of one or two arguments. In the former case, the integer
designates a field within the structure that should contain a
procedure; the integer must be between @racket[0] (inclusive) and the
number of non-automatic fields in the structure type (exclusive, not
counting supertype fields), and the designated field must also be
specified as immutable.
If the property value is a procedure of one argument, then the
procedure serves as the transformer for match expansion. If the property value is a procedure of two
arguments, then the first argument is the structure whose type has
@racket[prop:match-expander] property, and the second argument is a
syntax object as for a @tech{match expander}..
If the property value is a @tech{assignment transformer}, then the wrapped
procedure is extracted with
@racket[set!-transformer-procedure] before it is called.
This binding is provided @racket[for-syntax].
}
@defthing[prop:legacy-match-expander struct-type-property?]{
Like @racket[prop:match-expander], but for the legacy match syntax.
This binding is provided @racket[for-syntax].
}
@defparam[match-equality-test comp-proc (any/c any/c . -> . any)]{
A @tech{parameter} that determines the comparison procedure used to check
whether multiple uses of an identifier match the ``same'' value. The
default is @racket[equal?].}
@deftogether[[@defform[(match/derived val-expr original-datum clause ...)]
@defform[(match*/derived (val-expr ...) original-datum clause* ...)]]]{
Like @racket[match] and @racket[match*] respectively, but includes a
sub-expression to be used as the source for all syntax errors within the form.
For example, @racket[match-lambda] expands to @racket[match/derived] so that
errors in the body of the form are reported in terms of @racket[match-lambda]
instead of @racket[match].}
@; ----------------------------------------------------------------------
@section{Library Extensions}
@defform*[[(== val comparator) (== val)]]{
A @tech{match expander}
which checks if the matched value is the same as @racket[val] when
compared by @racket[comparator]. If @racket[comparator] is
not provided, it defaults to @racket[equal?].
@examples[#:eval match-eval
(match (list 1 2 3)
[(== (list 1 2 3)) 'yes]
[_ 'no])
(match (list 1 2 3)
[(== (list 1 2 3) eq?) 'yes]
[_ 'no])
(match (list 1 2 3)
[(list 1 2 (== 3 =)) 'yes]
[_ 'no])
]
}
@defform[(struct* struct-id ([field pat] ...))]{
A @racket[match] pattern form that matches an instance of a structure
type named @racket[struct-id], where the field @racket[field] in the
instance matches the corresponding @racket[pat].
Any field of @racket[struct-id] may be omitted, and such fields can
occur in any order.
@defexamples[
#:eval match-eval
(define-struct tree (val left right))
(match (make-tree 0 (make-tree 1 #f #f) #f)
[(struct* tree ([val a]
[left (struct* tree ([right #f] [val b]))]))
(list a b)])
]
}
@; ----------------------------------------------------------------------
@close-eval[match-eval]