#lang scribble/doc @(require scribble/manual scribble/eval "guide-utils.ss" (for-label racket/match)) @(begin (define match-eval (make-base-eval)) (interaction-eval #:eval match-eval (require racket/match))) @title[#:tag "match"]{Pattern Matching} The @racket[match] form supports pattern matching on arbitrary Racket values, as opposed to functions like @racket[regexp-match] that compare regular expressions to byte and character sequences (see @secref["regexp"]). @specform[ (match target-expr [pattern expr ...+] ...) ] The @racket[match] form takes the result of @racket[target-expr] and tries to match each @racket[_pattern] in order. As soon as it finds a match, it evaluates the corresponding @racket[_expr] sequence to obtain the result for the @racket[match] form. If @racket[_pattern] includes @deftech{pattern variables}, they are treated like wildcards, and each variable is bound in the @racket[_expr] to the input fragments that it matched. Most Racket 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 @racket[cons], @racket[list], and @racket[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]) ] A constructor bound with @scheme[struct] also can be used as a pattern constructor: @interaction[ #:eval match-eval (struct shoe (size color)) (struct hat (size style)) (match (hat 23 'bowler) [(shoe 10 'white) "bottom"] [(hat 23 'bowler) "top"]) ] Unquoted, non-constructor identifiers in a 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 (hat 23 'bowler) (hat 22 'pork-pie)) [(list (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 @racketmodname[racket/match]. Forms like @racket[match-let] and @racket[match-lambda] support patterns in positions that otherwise must be identifiers. For example, @racket[match-let] generalizes @racket[let] to a @as-index{destructing bind}: @interaction[ #:eval match-eval (match-let ([(list x y z) '(1 2 3)]) (list z y x)) ] For information on these additional forms, see @racketmodname[racket/match]. @refdetails["match"]{pattern matching} @close-eval[match-eval]