Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Common Lisp - Pattern Matching

I'm trying to write a function which compare two lists in Common Lisp.

The sign ’&’ indicates any sequence of elements and the sign ’$’ indicates any single element.

(defun match (filter data)
     (cond
        ((atom filter) (eq filter data))
        ((atom data) NIL)
        ((eq (car filter) '|$|)
           (match (cdr filter) (cdr data)))
        ((eq (car filter) '|&|)
           (cond
             ((match (cdr filter) data))
             (data (match filter (cdr data)))))
        ((match (car filter) (car data))
            (match (cdr filter) (cdr data)))))

which works fine :

(match '(a b c) '(a b c)) ; => T
(match '(a $ c) '(a b c)) ; => T
(match '(a ff c) '(a b c)) ; => NIL
(match '(a & c) '(a z b c)) ; => T

I would like to add a new filter (with the% symbol) which allows the choice between different possible elements, for example

(match '(a %(b 1) c) '(a b c)) ; => T
(match '(a %(b 1) c) '(a 1 c)) ; => T
(match '(a %(b 1) c) '(a z c)) ; => NIL
like image 862
Nielwig Avatar asked Apr 21 '26 15:04

Nielwig


1 Answers

You have to try all the elements in the sublist after % to see if any of them, combined with the rest of the filter, matches the data:

(defun match (filter data)
     (cond
        ((atom filter) (eq filter data))
        ((atom data) NIL)
        ((eq (car filter) '|$|)
           (match (cdr filter) (cdr data)))
        ((eq (car filter) '|&|)
           (cond
             ((match (cdr filter) data))
             (data (match filter (cdr data)))))
        ((eq (car filter) '|%|)
          (some #'(lambda (f) (match (cons f (cddr filter)) data)) (cadr filter)) )
        ((match (car filter) (car data))
            (match (cdr filter) (cdr data)))))

You should also add some checking steps to ensure that the filter is correctly formed, i.e. that the element after % is a list, etc...

like image 78
Leo Avatar answered Apr 25 '26 14:04

Leo



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!