racket/match (included in racket, not in racket/base) takes values apart by shape. A pattern says what a value looks like and names the parts; match tries each pattern in turn and runs the body of the first that fits, with the names bound. Patterns are read symbolically: the words list, cons, ? and the rest mean what they mean here whether or not the program binds them.
The forms
| Form | Meaning |
|---|---|
(match val-expr [pat option … body …+] …) | the first clause whose pattern matches; if none does, exn:misc:match? is raised. The last body is in tail position |
(match* (val-expr …+) [(pat …+) option … body …+] …) | matches several values at once; a clause needs one pattern per value |
(match/values expr [(pat …+) body …+] …) | matches the several values expr returns |
(match-lambda clause …), match-λ | a one-argument procedure that matches its argument |
(match-lambda* clause …) | matches the list of all arguments |
(match-lambda** clause* …) | matches several arguments, one pattern each |
(match-let ([pat expr] …) body …+), match-let*, match-letrec, match-let-values, match-let*-values, match-letrec-values | let forms whose bindings are patterns |
(match-define pat expr), (match-define-values (pat …) expr) | a definition whose left side is a pattern: (match-define (list a b) '(1 2)) |
(define/match (f arg …) match*-clause …) | a function defined by clauses over its arguments; arguments may be optional or keyword arguments, and the head may be curried |
(failure-cont) | the lower-level way to make a match fall through to the next clause |
(match-equality-test) | a parameter: the test used when one name appears twice in a pattern (default equal?) |
(define-match-expander id proc-expr), match/derived, match*/derived | define a new pattern, and the building blocks for writing a match-like form |
Clause options
A clause is [pat option … body …+]. The options, which may repeat, are:
#:when cond-expr– the clause matches only if the expression, which sees the pattern's names, is true;#:do [do-body …]– runs forms (including definitions) that later options and the body can see;(=> id), written straight after the pattern – bindsidto a procedure of no arguments that, when called, abandons this clause and goes on matching with the next. The bodies must not change the matched value before calling it.
Unlike cond and case, else is not special in match: a bare else is a pattern variable. The catch-all pattern is _.
The patterns
| Pattern | Matches |
|---|---|
id, (var id) | anything, and binds it to id. A name used twice must match two values equal under (match-equality-test), except in different or or not branches. The reserved names are _, ..., ___, ..k and __k |
_ | anything, binding nothing |
#t #f string, bytes, number, character, 'datum | a value that is equal? to that constant |
(list pat …) | a list of exactly those elements. A pattern followed by ... (or ___) matches zero or more elements; ..k (or __k) matches k or more. A name under an ellipsis is bound to a list. (list 1 a ..3 5) matches '(1 2 2 2 5) |
(list-rest pat … tail-pat), (list* …) | like list, but the last pattern matches what is left, which may be an improper tail |
(list-no-order pat …) | a list whose elements match the patterns in any order; a final pattern with an ellipsis takes the elements that match no other pattern |
(vector pat …) | a vector, like list |
(cons pat1 pat2), (mcons pat1 pat2), (box pat) | a pair, a mutable pair, a box |
(hash key-expr pat … [#:open | #:closed | #:rest pat]) | a hash table that has each key (key-expr is an expression, compared with the table's own comparison) with a value matching the pattern. By default, or with #:closed, the table has no other keys; #:open allows others and #:rest pat matches the remaining table. Added in version 8.11.1.10 |
(hash* [key-expr pat kv-option] … ht-option) | like hash, with each pair in brackets, open by default, and #:default expr for a missing key |
(hash-table (pat pat) …) | an older pattern: key and value patterns in pairs, in any order, matching the whole table |
(struct-id pat …), (struct struct-id (pat …)) | an instance of the structure type; one pattern per field, including the supertypes' fields. (struct struct-id _) matches any instance regardless of fields |
(struct* struct-id ([field pat] …)) | an instance, matching only some fields, in any order and by name; the supertypes' fields are not named |
(regexp rx-expr), (regexp rx-expr pat), (pregexp …) | a string (or byte string) that the regular expression matches; the second form matches the result of regexp-match, a list of the whole match and its groups, against pat |
(and pat …) | all patterns match; (and id pat) names the whole value |
(or pat …) | any pattern matches; every branch must bind the same names |
(not pat …) | none of the patterns match (binds nothing) |
(app expr pat …) | applies the procedure expr to the value and matches the result against pat (several patterns if it returns several values) |
(? expr pat …) | the predicate expr is true of the value and every pat matches it: (? number? n) |
(== val), (== val comparator) | a value equal to val (an expression) under equal? or the comparator. A library match expander |
`qp (quasiquote) | a datum written with quasiquote, where ,pat and ,@pat hold patterns: `(add ,a ,b) matches '(add 1 2) |
| a derived pattern | one made with define-match-expander or a structure that has prop:match-expander |
#lang racket
(struct add (l r))
(struct mul (l r))
(define (eval-expr e)
(match e
[(? number? n) n]
[(add l r) (+ (eval-expr l) (eval-expr r))]
[(mul l r) (* (eval-expr l) (eval-expr r))]
[`(neg ,x) (- (eval-expr x))]
[(list 'sum (? number? ns) ...) (apply + ns)]
[_ (error 'eval-expr "bad expression: ~e" e)]))
(match '(1 2 3 4)
[(list 1 a ..3) a] ; '(2 3 4)
[_ 'no])
(match (hash "a" 1 "b" 2)
[(hash "b" b #:open) b]) ; 2
(match-define (list x y) '(10 20))
(define/match (area shape)
[((list 'circle r)) (* 3 r r)]
[((list 'rect w h)) (* w h)])
Match expanders
(define-match-expander name transformer [expr-transformer]) makes name a pattern: the transformer takes the pattern syntax and returns a pattern that uses the built-in ones. If a second transformer is given, name is also usable as an expression. A structure with prop:match-expander does the same.
How the viewer colours patterns
In match, match*, match-lambda, match-let, match-define and define/match the first part of each clause is read as a pattern: its names are variables, the pattern keywords above are keywords, a constructor name of a structure is a function, the ... and _ are keywords, and the expressions inside ?, app, ==, regexp and hash keys are read as code.
Not described
Known, not yet covered
- Reference: the sections on non-linear patterns with ellipses (how one name at several depths is rejected), the details of
hash*options, the structure of match expanders (syntax-case-style procedures andprop:legacy-match-expander), and the library patterns beyond==andstruct*were not read. - Viewer: a pattern inside
quasiquoteshows the unquoted parts as code, not as patterns;#:whenand#:dooptions are read as code, which is right, and a pattern written with a user-defined match expander has its head coloured as a function call.
See also
- Structs – the types that
structpatterns match - Strings and regexps – the regular expressions behind
regexppatterns - Macros –
syntax-parsepatterns andsyntax-case, which are different