(defmatch calculate ((?x plus ?y))
(+ #?x #?y))
(defmatch calculate ((?x minus ?y))
(- #?x #?y))
The first method is defined to be applicable to an argument matching the pattern (?x plus ?y). The use of the "?" character prefixes the name of a matcher variable in common with other pattern matchers. The pattern (?x plus ?y) will match with any three element list containing the symbol "plus" as its second element.
The use of symbols like "#?x" in the body of the method definition is to retrieve the value of a matcher variable (see note).
calculate is used as follows:
> (calculate '(5 plus 3)) ==> 8
> (calculate '(5 minus 3)) ==> 2
In each case the calculate method used is that which matches the argument provided.
The matcher which underpins the use of DEFMATCH provides various matcher directives/tags. In addition to the single "?" prefix for matcher variables (for matching with single list elements). The "??" prefix will bind to zero or more list elements. This allows methods to be defined in a Prolog-like style and provides an alternative approach to structuring recursive forms. An example of this is a pair of list length methods (other prefixes).
(defmatch len1 (()) 0)
(defmatch len1 ((??x))
(1+ (len1 (rest #?x))))
> (len1 '(herring haddock hake)) ? 3
Note that where more than one method is applicable (because two or more match the argument provided) the method used is always the one which was defined first, like Prolog. Unlike Prolog there is no backtracking so other methods will never be invoked.
An example of MLET in use follows, note that matcher forms other than DEFMATCH need their patterns to be quoted - this allows patterns to be dynamically constructed or stored in variables.
> (mlet ('(the ?subj ate the ?obj)
'(the mouse ate the cheese))
(list #?subj #?obj))
==> (MOUSE CHEESE)
Two other matcher tags act as wildcards. These are "=" and "==" which are the matching tag for a single element wildcard and multiple element wildcard respectively.
> (mlet ('(= ?2nd == ?last) '(a b c d e f g))
(list #?2nd #?last))
==> (B G)
;; a simple set of facts concerning 4 boxes
'((isa b1 box) (color b1 red) (size b1 large)
(isa b2 box) (color b2 red) (size b2 small)
(isa b3 box) (color b3 blue) (size b3 small)
(isa b4 box) (color b3 blue) (size b4 small)
(supports b1 b2) (supports b2 b3)
FOREACH iterates with single patterns, FOREVERY with multiple patterns...
> (foreach ('(size ?x small) db1)
(format T "~&~a is small" #?x) ; side effect
#?x) ; result values
==> B2 is small
==> B3 is small
==> B4 is small
==> (B2 B3 B4)
> (forevery ('((isa ?b box)(color ?b red)
(supports ?b ?x)) db1)
(format T "~&~a is a red block which supports ~a"
(list 'red-block #?b)) ; value returned
==> B1 is a red block which supports B2
==> B2 is a red block which supports B3
==> ((RED-BLOCK B1) (RED-BLOCK B2))