m2ym / optima

Optimized Pattern Matching Library for Common Lisp
271 stars 19 forks source link

question about _ variable #106

Closed arademaker closed 9 years ago

arademaker commented 9 years ago

In the docs, the _ is used to match the whole input. I wonder if it can be use to match part of the input. In the example

(match (list (car frm) sign)
      ('(and true)  1)
      ('(and false) 2)
      ('(or true)   2)
      ('(or false)  1)
      ('(implies true)  2)
      ('(implies false) 1)
      ((or '(not true) '(not false)) 1))

I would like to replace the case (or '(not true) '(not false) with something like '(not _) or similar. Is it possible?

m2ym commented 9 years ago

Do you want to match something other than true or false? If so, you can write a pattern like (not (or 'true 'false)).

guicho271828 commented 9 years ago

The question might be identical to: how does the quote pattern behave? Does it use eq,eql,equal,equalp and similar

(match '(not _) ('(not _) t) (_ nil)) ;; --> t
(match '(not x) ('(not _) t) (_ nil)) ;; --> nil

or does it destructure the subpatterns?

(match '(not _) ('(not _) t) (_ nil)) ;; --> t
(match '(not x) ('(not _) t) (_ nil)) ;; --> t

now the readme only reads: A constant-pattern matches the constant itself

m2ym commented 9 years ago

Any symbols within quote pattern cannot be variables. So a possible answer is (list 'not _).

m2ym commented 9 years ago

Using fare-quasiquote, you can write a pattern like:

`(not ,_)
guicho271828 commented 9 years ago

(match (vector 0 0 0) (#(0 0 0) t) (_ nil)) should or should not return t. hmm, It might need to be addressed in the readme.

arademaker commented 9 years ago

@m2ym , it does not work:

cl-user> (optima:match '(not true)
       ('(and false) 1)
       ('(list 'not _) 2))
nil
arademaker commented 9 years ago

@m2ym the quasiquote doesn't work too

cl-user> (optima:match '(not true)
       ('(and false) 1)
       (`(not ,_) 2))
attempt to call `backquotep' which is an undefined function.
   [Condition of type undefined-function]
arademaker commented 9 years ago

So far, the only solution that I found was using the or construtor. This is ok for my code, but I would like to have a more concise way to say "not follow by anything".

cl-user> (optima:match '(not true)
                 ('(and false) 1)
                 ((or '(not true) '(not false)) 2))
2

The code is used in my tableaux (https://github.com/arademaker/LP-2014-2/blob/master/cl/tableaux.lisp#L60)!

guicho271828 commented 9 years ago

@arademaker make sure you have followed the instruction at http://cliki.net/fare-quasiquote . If you have done (asdf:use-package :fare-quasiquote) and use-package only, it is not enough because the new readtable for fare-quasiquote is not activated.

m2ym commented 9 years ago

This is an answer.

(optima:match '(not true)
       ('(and false) 1)
       ((list 'not _) 2))

Maybe you should carefully read README, especially about pattern language specification.

arademaker commented 9 years ago

@m2ym , you are right! the (list 'not _) worked fine! My mistake, I forgot the quote before the list.

m2ym commented 9 years ago

Great.