1 Welcome to PLT Scheme
2 Scheme Essentials
3 Built-In Datatypes
4 Expressions and Definitions
5 Programmer-Defined Datatypes
6 Modules
7 Contracts
8 Input and Output
9 Regular Expressions
10 Exceptions and Control
11 Iterations and Comprehensions
12 Pattern Matching
13 Classes and Objects
14 Units (Components)
15 Reflection and Dynamic Evaluation
16 Macros
17 Performance
18 Running and Creating Executables
19 Compilation and Configuration
20 More Libraries
Bibliography
Index
Version: 4.0.2

 

12 Pattern Matching

The match form supports pattern matching on arbitrary Scheme values, as opposed to functions like regexp-match that compare regular expressions to byte and character sequences (see Regular Expressions).

(match target-expr

  [pattern expr ...+] ...)

The match form takes the result of target-expr and tries to match each pattern in order. As soon as it finds a match, it evaluates the corresponding expr sequence to obtain the result for the match form. If pattern includes pattern variables, they are treated like wildcards, and each variable is bound in the expr to the input fragments that it matched.

Most Scheme literal expressions can be used as patterns:

  > (match 2

      [1 'one]

      [2 'two]

      [3 'three])

  two

  > (match #f

      [#t 'yes]

      [#f 'no])

  no

  > (match "apple"

      ['apple 'symbol]

      ["apple" 'string]

      [#f 'boolean])

  string

Constructors like cons, list, and vector can be used to create patterns that match pairs, lists, and vectors:

  > (match '(1 2)

      [(list 0 1) 'one]

      [(list 1 2) 'two])

  two

  > (match '(1 . 2)

      [(list 1 2) 'list]

      [(cons 1 2) 'pair])

  pair

  > (match #(1 2)

      [(list 1 2) 'list]

      [(vector 1 2) 'vector])

  vector

The struct construct matches an instance of a particular structure type:

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

  "top"

Unquoted, non-constructor identifiers in an pattern are pattern variables that are bound in the result expressions:

  > (match '(1)

      [(list x) (+ x 1)]

      [(list x y) (+ x y)])

  2

  > (match '(1 2)

      [(list x) (+ x 1)]

      [(list x y) (+ x y)])

  3

  > (match (make-hat 23 'bowler)

      [(struct shoe (sz col)) sz]

      [(struct hat (sz stl)) sz])

  23

An ellipsis, written ..., 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:

  > (match '(1 1 1)

      [(list 1 ...) 'ones]

      [else 'other])

  ones

  > (match '(1 1 2)

      [(list 1 ...) 'ones]

      [else 'other])

  other

  > (match '(1 2 3 4)

      [(list 1 x ... 4) x])

  (2 3)

  > (match (list (make-hat 23 'bowler) (make-hat 22 'pork-pie))

      [(list (struct hat (sz styl)) ...) (apply + sz)])

  45

Ellipses can be nested to match nested repetitions, and in that case, pattern variables can be bound to lists of lists of matches:

  > (match '((! 1) (! 2 2) (! 3 3 3))

      [(list (list '! x ...) ...) x])

  ((1) (2 2) (3 3 3))

For information on many more pattern forms, see scheme/match.

Forms like match-let and match-lambda support patterns in positions that otherwise must be identifiers. For example, match-let generalizes let to a destructing bind:

  > (match-let ([(list x y z) '(1 2 3)])

      (list z y x))

  (3 2 1)

For information on these additional forms, see scheme/match.

Pattern Matching in Reference: PLT Scheme provides more on pattern matching.