TXR Lisp – an innovative, original dialect from the Lisp language family
nongnu.org
nongnu.org
A pattern matching implementation is badly needed for Lisp programming, holding up work that benefits from it, like compiler work.
In terms of programmer interface, there are two "schools" for writing pattern matchers: "match by printed notation" and "match by code". Succinctly: match by code means (list a b) matches (1 2), binding (a 1) (b 2). Match by printed notation means that you have something like (@a @b) instead which looks like (1 2) but with explicitly denoted variables. Some "match by code" systems make some use of backquote for this: `(,a ,b) matches (1 2). I think Fare's matcher has something like this, for which it carried its own backquote implementation.
I'm not attracted to "match by code". It doesn't scale to nested objects. Code for constructing complicated, nested objects looks ugly. That's why Lisp got backquote fifty years ago already. There can be many code variants that produce the same thing. The user will be annoyed if (cons a b) is a valid pattern, but (list* a b) isn't supported as an equivalent. How far do you take it? Should (mapcar 'succ a) be a valid pattern which binds a to (0 1 2) for the input (1 2 3)? I do have to acknowledge that simple cases of "match by code" are readable.
TXR Lisp has support in its syntax for the future implementation of "match by notation". The syntax @ident produces the form (sys:var ident). ident can be a symbol, or integer token. The former case is called "meta-varialble"; the latter "meta-number". The syntax @expr produces (sys:expr expr), where expr can be a (...) or [...] compound (the latter being sugar for (dwim ...). These notations can be coupled to a pattern matching system. For instance, if we have a point structure with x y members, we could have a pattern like #S(point x @column y @row). This is valid read syntax now:
1> (defstruct point () x y)
#<struct-type point>
2> #S(point x @col y @row)
#S(point x @col y @row)
3> *2.x
@col
4> (car *2.x)
sys:var
5> (cadr *2.x)
col
So we can imagine (match-case some-obj
(#S(point x @col y @row) ... col and row are bound ...))
kind of thing.