S9 LIB  (define make-matcher symbol <clause> ...)           ==>  procedure
        (define-matcher symbol <clause> ...)                ==>  unspecific
        (let-matcher symbol (<clause> ...) expression ...)  ==>  unspecific
        (ml-match name <program>)                           ==>  unspecific

        (load-from-library "matcher.scm")

These constructs allow to write programs using pattern matching
style.

The MAKE-MATCHER procedures creates a matcher from the given
<clause>s. Each <clause> must have the form

(<pattern> <expression> ...)

where <pattern> is a Scheme list and <expression> is an
arbitrary expression. MAKE-MATCHER returns a procedure which
matches its arguments against each given <pattern> and evaluates
the expressions associated with the first matching pattern.

Patterns are matched as follows:

- A list is matched by matching its members recursively.
- Atomic objects except for symbols match themselves;
- Symbols match any value and bind the symbol to that value;
  the <expression>s will be evaluated with these bindings in
  effect;
- The symbol _ matches any value, but does not bind to it;
- A quoted symbol matches the symbol being quoted.

The SYMBOL passed to MAKE-MATCHER is the name of the resulting
matcher. It is merely used for error reporting. In order for
a matcher to recurse, it must be bound using DEFINE-MATCHER
or LET-MATCHER.

DEFINE-MATCHER binds a matcher to a symbol at the toplevel.
A procedure resembling LENGTH may be written in this way using
DEFINE-MATCHER:

(define-matcher len
  ((())      0)               ; The empty list has a length of 0.
  (((_ . x)) (+ 1 (len x))))  ; A list whose car part does not
                              ; matter and whose cdr part is X
                              ; has a length of 1 plus the length
                              ; of X.

LET-MATCHER binds a matcher locally. Here is the above matcher
as a local definition:

(let-matcher len
  (((())      0)
   (((_ . x)) (+ 1 (len x))))
  (len '(a b c)))

ML-MATCH is like DEFINE-MATCHER, but expects an ML-style <program>
rather than a set of <clauses>. A <program> is a series of Scheme
datums with the following syntax:

<program>  :=  <clause>
           |   <clause> : <program>
<clause>   :=  <pattern> = <expression> ...

Here is the LEN function using ML-MATCH:

(ml-match
  len (())      = 0
    : ((_ . x)) = (+ 1 (len x)))

(It uses : instead of | to separate cases, because | is not
 a valid Scheme symbol.)

The following more elaborate example implements a subset of
ML-MATCH by using pattern matching itself. The only difference
to ML-MATCH is that it does not allow multiple expressions in
bodies:

(define-syntax (simple-match name . clauses)
  (let-matcher next-clause
    (((out ())
       (reverse out))
     ((out (pattern '= expr ': . clauses))
       (next-clause `((,pattern ,expr) ,@out) clauses))
     ((out (pattern '= expr))
       (next-clause `((,pattern ,expr) ,@out) ())))
    `(define ,name
       ,(apply make-matcher name (next-clause '() clauses)))))

(begin
  (define-matcher len
    ((())      0)
    (((_ . x)) (+ 1 (len x))))
  (len '(a b c d e f)))
                              ==>  6
(let-matcher fac
  (((x)   (fac x 1))
   ((0 r) r)
   ((x r) (fac (- x 1) (* x r))))
  (fac 10))
                              ==>  3628800
(begin
  (ml-match
    appnd (() x)      = x
        : ((h . t) x) = (cons h (appnd t x)))
  (appnd '(a b c) '(d e f)))
                              ==>  (a b c d e f)
