Note: This matcher is the basis of the matcher used by the Lisp Critic. It does CAR/CDR matching of lists. This is different than the matching logic for JSON-like lists of properties.
These exercises ask you to write extensions to match.lisp. The matcher is introduced here. How it is extended is described here.
To do them, load the matcher like this:
(ql:quickload "match")
This creates two packages:
- match-tests where all the test cases are are defined
- exmatch where the extensible matcher is define
To do the exercises
- Create a file that begins with
(in-package #:exmatch)
Put your answer code there to save and load. - In the Lisp Listener, do
(in-package #:match-tests)
. Run all your tests there.
The exmatch package already exports the names of the functions to be defined for the exercises.
To test any particular exercise, just run the tests for that
specific pattern extension. But before submitting your answers,
do (run-tests)
with no arguments, to run all the
match tests. Make sure that all tests pass, except those for any
exercise you haven't done yet.
A few examples are given here of each extension, but there are far many more tests
in match.lisp. Study those
tests before coding an answer. Also study how the existing extensions, such
as ?and
and ??
, work as well.
MATCH-OR, MATCH-NOT, MATCH-=
Define the pattern function ?or
such that
the pattern (?or pattern1 pattern2 ...)
returns bindings
for every pattern that matches the input.
> (match-p '(?or a b) 'b) (NIL) > (match-p '(?or a b) 'c) NIL > (match-p '(?x ?y (?or ?x ?y ?z)) '(a b a)) (((?Y . B) (?X . A)) ((?Z . A) (?Y . B) (?X . A)))
Define the pattern function ?not
such that
the pattern (?not pattern) matches an input if and only
if pattern does not match that input.
> (match-p '(?not a) 'a) NIL > (match-p '(?not b) 'a) (NIL) (match-p '(?not ?x) 'a) NIL > (match-p '(?x (?not ?x)) '(a b)) (((?X . A)))
Note that some of the test cases for ?not
require
?or
to be defined first.
The matcher already defines (?? function)
to return a match if function returns true for the object, e.g.,
(?? numberp)
will match any number. Additional arguments to
the function can be specified in the pattern, e.g., (?? > 5)
will match anything greater than 5. This exercise
asks you to define ?=
to match a pattern to the result
of applying a function to the object. The syntax is
(?= pattern function argument1 argument2 ...)
.
When this is matched against an object, it first calls
(function object argument1 argument2 ...)
, and then matches
pattern against the result.
> (defun square (x) (* x x)) SQUARE > (match-p '(?= ?x square) 3) (((?X . 9))) > (defun add-title (name title) (cons title name)) ADD-TITLE >(match-p '(?= ?name add-title professor) '(john smith)) (((?NAME PROFESSOR JOHN SMITH)))
MATCH-CONTAINS
Define the pattern function ?contains
such that
the pattern (?contains pattern) matches an input if and only
if pattern matches the input or some subexpression of the input.
Note: the order of variable bindings doesn't matter.
> (match-p '(?contains ?x) 'a) (((?X . A))) > (match-p '(?contains (?and (?? numberp) ?x)) '((a 12) c (((5))))) (((?X . 5)) ((?X . 12)))