Pattern Matching

Adds native pattern matching to Scheme. Supports pattern-oriented dispatch of function arguments (pdefine), pattern bindings in let-like statements (plet) and pattern switch statements (pcase). The pattern language was inspired by the 6.945 Pattern Matcher, although no code was borrowed.

Pattern language reference is available here.

Macros

plet ({(pattern datum)}) body

Matches patterns against datums, and executes body in an environment with pattern variables bound. For example, here's how one might use plet to implement vector addition, where a vector is a cons pair:

 (define vec1 (cons 1 2))
 ;Value: vec1

 (define vec2 (cons 3 4))
 ;Value: vec2

 (define (vector-add x y)
   (plet (((?x1 . ?x2) x)
          ((?y1 . ?y2) y))
         (cons (+ x1 y1) (+ x2 y2))))
 ;Value: vector-add

 (vector-add vec1 vec2)
 ;Value 86: (4 . 6)

plet* ({(pattern datum)}) body

Like plet, but each subsequent pattern-datum pair is evaluated in an environment with all previous matches bound.

(plet* ((p1 d1)
        (p2 d2)
        ...
        (pn dn))
       e1
       e2
       ...)
is equivalent to
(plet ((p1 d1))
      (plet ((p2 d2))
            ...
            (plet ((pn dn)
                   e1
                   e2
                   ...)))).

pdefine (name {argument pattern}) body

Defines a procedure that dispatches based on argument patterns. For example, pdefine might be used to define the factorial function:

(pdefine (fact 0) 1)
;Value: ok

(pdefine (fact ?n) (* n (fact (-1+ n))))
;Value: ok

(fact 5)
;Value: 120
Similarly, one might use pdefine to implement vector addition:
(pdefine (vector-add (?x1 . ?x2) (?y1 . ?y2))
         (cons (+ x1 y1) (+ x2 y2)))
;Value: ok

(vector-add (cons 1 2) (cons 3 4))
;Value 89: (4 . 6)
Argument patterns can utilize all features of the pattern language, such as variable-length segments. In the example below. Anonymous segment patterns are used to check whether a list contains at least one number:
(pdefine (has-number? (??prefix (? num ,number?) ??suffix)) #t)
;Value: ok

(pdefine (has-number? ?obj) #f)
;Value: ok

(has-number? '(a b c 1 d e))
;Value: #t

(has-number? '(a b c d e))
;Value: #f
Note: Functions created using pdefine are bound in user-initial-environment.

pcase datum {(pattern {expression})}

Looks for the first pattern that matches datum, and executes the associated expressions in an environment with bound pattern variables, returning then result. If no patterns match. the return value is undefined.

Example:

(pdefine (find ?elt ?a-list)
         (pcase a-list
                ((??prefix ,elt ??suffix) elt)
                (? #f)))
;Value: ok

(find 1 '(2 3 4 5))
;Value: #f

(find 1 '(2 3 a b 1 7 8))
;Value: 1

(find 'b '(2 3 a b 1 7 8))
;Value: b


Scheme Power Tools Documentation
(c) Maciej Pacula 2010-2011
http://mpacula.com