(rapid match)

A pattern matcher.This pattern matcher is a portable version of Chez Scheme's match by Dan Friedman, Erik Hilsdale, and Kent Dybvig.

Pattern matcher

A match expression looks a lot like a case expression, except that the keys are replaced with a pattern to match against the input. A match expression has the general form

(match <expr> <clause> ...), where <expr> in the input expression to match and each clause has one of the forms

(<pattern> <body1> <body2> ...), and

(<pattern> (guard <guard-expr>) <body1> <body2> ...). As with case, the input expression is evaluated to produce the input value and the first clause the input value matches, if any, is selected. The body <body1> <body2> ... of the selected clause is evaluated in sequence, and the values of the last expression are returned. An input value matches a clause if it fits the clause's pattern and the guard expression <guard-expr>, if any, evaluates to a true value. Patterns may contain symbolic constants, which must match exactly, and pattern variables, which match any input. Pattern variables are prefixed by commas; symbolic constants are not.
(match '(a 17 37)
  ((a ,x) 1)
  ((b ,x ,y) 2)
  ((a ,x ,y) 3))
=> 3
The first clause fails to match because there are three items in the input list, and the pattern has only two. The second clause fails because b does not match a. In the output expression, the values of the pattern variables are bound to the corresponding pieces of input.
(match '(a 17 37)
  ((a ,x) (- x))
  ((b ,x ,y) (+ x y))
  ((a ,x ,y) (* x y)))
=> 629
When followed by an ellipsis (...), a pattern variable represents a sequence of input values.
(match '(a 17 37) ((a ,x* ...) x*))
=> (17 37)
Ellipses can follow a structures pattern containing one or more pattern variables.
(match '(begin (1 5) (2 6) (3 7) (4 8))
  ((begin (,x* ,y*) ...) (append x* y*))) 
=> (1 2 3 4 5 6 7 8)
Ellipses can be nested, producing sequences of sequences of values.
(match '((a b c d) (e f g) (h i) (j))
  (((,x* ,y** ...) ...) (list x* y**)))
=> ((a e h j) ((b c d) (f g) (i) ()))
Recursion is frequently required while processing an input expression with match. Here, a procedure returning the length of a list is defined.
(letrec
    ((len
      (lambda (lst)
        (match lst
          (() 0)
          ((,x ,x* ...) (+ 1 (len x*)))))))
  (len '(a b c d)))
=> 4
A simpler version of the above uses the catamorphism feature of match. If a pattern variable is written as ,(<var>), match recurs on the matching subpart of the input before evaluating the output expressions of the clause.
(let ((len
       (lambda (lst)
         (match lst
           (() 0)
           ((,x . ,(x*)) (+ 1 x*))))))
  (len '(a b c d)))
=> 4
In some cases, match will need to return multiple values. The catamorphism syntax can be used to receive multiple values. When making implicit recursive calls using the catamorphism syntax, zero or more variables between the brackets can be included, each representing one of the expected return values.
(let ((split
       (lambda (lis)
         (match lis
           (() (values '() '()))
           ((,x) (values `(,x) '()))
           ((,x ,y . ,(odds evens)) (values `(,x . ,odds)
                                            `(,y . ,evens)))))))
  (split '(a b c d e f)))
=> ((values) (a c e) (b d f))
Sometimes it is useful to explicitely name the operator in a catamorphism subpattern. Whereas ,(<var> ...) recurs to the top of the current match, ,(<cata> -> <var> ...) recurs to <cata>. <Cata> must evaluate to a procedure that accepts one argument, the input expression, and returns as many values as there are identifiers following the ->. Here is an example that illustrates the use of guards and how to achieve the effect of a catch-all clause.
(let ((simple-eval
       (lambda (x)
         (match x
           (,i (guard (integer? i)) i)
           ((+ ,(x*) ...) (apply + x*))
           ((* ,(x*) ...) (apply * x*))
           ((- ,(x) ,(y)) (- x y))
           ((/ ,(x) ,(y)) (/ x y))
           (,x (error "simple-eval: invalid expression" x))))))
  (simple-eval '(+ (- 0 1) (+ 2 3))))
=> 4

Syntax

(match <expr> <clause> ...)

The result of <expr> is matched against each <clause> in turn, according to the rules described in the previous section, until the the first clause matches. When a match is found, the corresponding body is evaluated, and the values of the last expression are returned as the result of the entire match. It is an error if no pattern matches.

(match* (<unbox> <loop>) <expr> <clause> ...)

Equivalent to the (match <expr> <clause> ...) with the following exceptions: If <unbox> is not #f, each input expression is converted with <unbox> before matched against a list or vector pattern. If <loop> is not #f, catamorphism subpatterns recur to <loop> if no explicit operator is named.

Auxiliary syntax

unquote

,

...

guard

->

Auxiliary syntax.