Pattern matching
Posted: Thu Sep 06, 2007 5:36 pm
Here is a quick way to use letex and unify to create a simple pattern matching syntax like those used in ocaml, erlang, haskell, et al. We use unify to match the pattern, so variables assigned in the pattern must be capitalized. These will be expanded in the body expression, so use capitals there as well.
The function foo is now defined in terms of the pattern of the argument, x. The two test expressions at the bottom evaluate:
When the match fails, it throws an error. This could be easily modified to evaluate to nil, but then you could not distinguish between a failed match and a successful match whose body evaluates to nil.
Code: Select all
(define-macro (letify)
(let ((pattern (eval (args 0))) (expr (args 1)))
(eval (expand (list letex pattern expr) 'pattern 'expr))))
(define-macro (when)
(letn ((var (args 0))
(pattern (args 1 0))
(expr (args 1 1))
(unification (unify pattern (eval var)))
(next (2 (args))))
(cond
(unification (eval (expand '(letify 'unification expr) 'unification 'expr)))
((null? next) (throw-error (string "Match failed against " x)))
(true (eval (cons 'when (cons var next)))))))
(define (foo x)
(when x
((A B C) (map println '(A B C)))
((A B C D) (map println '(A B C D)))
((A B C D E F) (map println '(A B C D E)))))
(foo '('THE 'QUICK 'BROWN 'FOX))
(foo '(1 2 3 4 5))
Code: Select all
THE
QUICK
BROWN
FOX
user error : Match failed against (1 2 3 4 5)
called from user defined function foo