标准的 Common Lisp 没有提供模式匹配,但是社区提供了一个 Trivia 库,参考 Trivia’s wiki
通过 quicklisp 加载
(ql:quickload :trivia)(use-package :trivia)
通用结构模式
cons
(match '(1 2 3)((cons x y); ^^ pattern(print x)(print y)));; |-> 1;; |-> (2 3)
list, list*
(match '(something #(0 1 2))((list a (vector 0 _ b))(value a b)))SOMETHING2(match '(1 2 . 3)((list* _ _ x)x))3
vector, vector*
(match #(1 2 3)((vector _ x _)x));; -> 2(match #(1 2 3 4)((vector _ x _)x));; -> NIL : does not match(match #(1 2 3 4)((vector* _ x _)x));; -> 2 : soft match.
<vector-pattern> : vector | simple-vectorbit-vector | simple-bit-vectorstring | simple-stringbase-string | simple-base-string | sequence(<vector-pattern> &rest subpatterns)
类别即结构模式
(defstruct foo bar baz)(defvar *x* (make-foo :bar 0 :baz 1)(match *x*;; make-instance style((foo :bar a :baz b)(values a b));; with-slots style((foo (bar a) (baz b))(values a b));; slot name style((foo bar baz)(values bar baz)))
type, satisfies
type 匹配对象的类型,satisfies 返回断言正确的对象,可以接受 lambda 函数。
assoc, property, alist, plist
会先检查是否是列表,然后在对列表里面的内容进行匹配
Array, simple-array, row-major-array 匹配
逻辑匹配
and, or
(match x((or (list 1 a)(cons a 3))a)
能够同时匹配 (1 2), (4 . 3),返回 2 和 4.
not
返回不匹配的值
guards
语法是 guard + subpattern + a test form 然后是主体
(match (list 2 5)((guard (list x y) ; subpattern(= 10 (* x y)) ; test-form(- x y) (satisfies evenp)) ; generator1, subpattern1t))
如果 subpattern 为真,执行测试语句,若测试语句也为真,执行 subpattern1。
返回 nil,因为 (- x y) == 3 不满足 evenp
嵌套匹配
(match '(:a (3 4) 5)((list :a (list _ c) _)c))
结果返回 4。
拓展阅读
参见 special patterns:place,bind 和 access。
