A pattern matcher.This pattern matcher is a portable version of Chez Scheme's match by Dan Friedman, Erik Hilsdale, and Kent Dybvig.
matchexpression looks a lot like a
caseexpression, 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.
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
(match '(a 17 37) ((a ,x) 1) ((b ,x ,y) 2) ((a ,x ,y) 3))
bdoes not match
a. In the output expression, the values of the pattern variables are bound to the corresponding pieces of input.
When followed by an ellipsis (
(match '(a 17 37) ((a ,x) (- x)) ((b ,x ,y) (+ x y)) ((a ,x ,y) (* x y)))
...), a pattern variable represents a sequence of input values.
Ellipses can follow a structures pattern containing one or more pattern variables.
(match '(a 17 37) ((a ,x* ...) x*))
=> (17 37)
Ellipses can be nested, producing sequences of sequences of values.
(match '(begin (1 5) (2 6) (3 7) (4 8)) ((begin (,x* ,y*) ...) (append x* y*)))
=> (1 2 3 4 5 6 7 8)
Recursion is frequently required while processing an input expression with
(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) ()))
match. Here, a procedure returning the length of a list is defined.
A simpler version of the above uses the catamorphism feature of
(letrec ((len (lambda (lst) (match lst (() 0) ((,x ,x* ...) (+ 1 (len x*))))))) (len '(a b c d)))
match. If a pattern variable is written as
matchrecurs on the matching subpart of the input before evaluating the output expressions of the clause.
In some cases,
(let ((len (lambda (lst) (match lst (() 0) ((,x . ,(x*)) (+ 1 x*)))))) (len '(a b c d)))
matchwill 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.
Sometimes it is useful to explicitely name the operator in a catamorphism subpattern. Whereas
(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))
,(<var> ...)recurs to the top of the current
,(<cata> -> <var> ...)recurs to
<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))))
<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 <expr> <clause> ...)with the following exceptions: If
#f, each input expression is converted with
<unbox>before matched against a list or vector pattern. If
#f, catamorphism subpatterns recur to
<loop>if no explicit operator is named.