racket/collects/scribblings/guide/match.scrbl

125 lines
3.2 KiB
Racket

#lang scribble/doc
@(require scribble/manual
scribble/eval
"guide-utils.ss"
(for-label scheme/match))
@(begin
(define match-eval (make-base-eval))
(interaction-eval #:eval match-eval (require scheme/match)))
@title[#:tag "match"]{Pattern Matching}
The @scheme[match] form supports pattern matching on arbitrary Scheme
values, as opposed to functions like @scheme[regexp-match] that
compare regular expressions to byte and character sequences (see
@secref["regexp"]).
@specform[
(match target-expr
[pattern expr ...+] ...)
]
The @scheme[match] form takes the result of @scheme[target-expr] and
tries to match each @scheme[_pattern] in order. As soon as it finds a
match, it evaluates the corresponding @scheme[_expr] sequence to
obtain the result for the @scheme[match] form. If @scheme[_pattern]
includes @deftech{pattern variables}, they are treated like wildcards,
and each variable is bound in the @scheme[_expr] to the input
fragments that it matched.
Most Scheme literal expressions can be used as patterns:
@interaction[
#:eval match-eval
(match 2
[1 'one]
[2 'two]
[3 'three])
(match #f
[#t 'yes]
[#f 'no])
(match "apple"
['apple 'symbol]
["apple" 'string]
[#f 'boolean])
]
Constructors like @scheme[cons], @scheme[list], and @scheme[vector]
can be used to create patterns that match pairs, lists, and vectors:
@interaction[
#:eval match-eval
(match '(1 2)
[(list 0 1) 'one]
[(list 1 2) 'two])
(match '(1 . 2)
[(list 1 2) 'list]
[(cons 1 2) 'pair])
(match #(1 2)
[(list 1 2) 'list]
[(vector 1 2) 'vector])
]
The @scheme[struct] construct matches an instance of a particular
structure type:
@interaction[
#:eval match-eval
(define-struct shoe (size color))
(define-struct hat (size style))
(match (make-hat 23 'bowler)
[(struct shoe (10 'white)) "bottom"]
[(struct hat (23 'bowler)) "top"])
]
Unquoted, non-constructor identifiers in an pattern are @tech{pattern
variables} that are bound in the result expressions:
@interaction[
#:eval match-eval
(match '(1)
[(list x) (+ x 1)]
[(list x y) (+ x y)])
(match '(1 2)
[(list x) (+ x 1)]
[(list x y) (+ x y)])
(match (make-hat 23 'bowler)
[(struct shoe (sz col)) sz]
[(struct hat (sz stl)) sz])
]
An ellipsis, written @litchar{...}, act like a Kleene star within a
list or vector pattern: the preceding sub-pattern can be used to match
any number of times for any number of consecutive elements of the list
of vector. If a sub-pattern followed by an ellipsis includes a pattern
variable, the variable matches multiple times, and it is bound in the
result expression to a list of matches:
@interaction[
#:eval match-eval
(match '(1 1 1)
[(list 1 ...) 'ones]
[else 'other])
(match '(1 1 2)
[(list 1 ...) 'ones]
[else 'other])
(match '(1 2 3 4)
[(list 1 x ... 4) x])
(match (list (make-hat 23 'bowler) (make-hat 22 'pork-pie))
[(list (struct hat (sz styl)) ...) (apply + sz)])
]
Ellipses can be nested to match nested repetitions, and in that case,
pattern variables can be bound to lists of lists of matches:
@interaction[
#:eval match-eval
(match '((! 1) (! 2 2) (! 3 3 3))
[(list (list '! x ...) ...) x])
]
For information on many more pattern forms, see @schememodname[scheme/match].
@close-eval[match-eval]