Skip to content

Latest commit

 

History

History
210 lines (155 loc) · 4.17 KB

pcase.org

File metadata and controls

210 lines (155 loc) · 4.17 KB

Pattern Matching with pcase

References

C-h f pcase
docstring
info:elisp#Pattern matching case statement
manual
Emacs: Pattern Matching with pcase
注意文中代码有几处有误
Pattern Matching in Emacs Lisp – Wilfred Hughes::Blog
跟 cl-destructuring-bind, dash.el, shadchen.el 的比较
EmacsWiki: Pattern Matching
一些例子

Examples

Hello World

(pcase '(1 2 (4 . 5) "Hello")
  (`(1 2 (4 . 5) ,(pred stringp))
   (message "It matched!")))

Match any list

(pcase '(a b c)
  ((and x (pred listp)) (message "Match List: %s" x)))

Notes that `(,_ . ,_) match any cons cell, i.e., any list except nil

(pcase '(a b c)
  ('nil "Match nil (empty list)")
  (`(,foo . ,bar)
   (message "Match non-empty list with car = %s and cdr = %s" foo bar)))

Repeated elements

By default, eq is used for testing:

If a SYMBOL is used twice in the same pattern the second occurrence becomes an ‘eq’uality test.

(pcase '(1 1)
  (`(,x ,x) (format-spec "Matching (%x %x) where %x eq %x" `((?x . ,x)))))

Here is an example of equal

(pcase '("1" "1")
  (`(,x ,(and y (guard (equal x y))))
   "Matching (%x %y) where %x equal %y"   
   (format-spec "Matching (%x %y) where %x equal %y"
                `((?x . ,(pp-to-string x)) (?y . ,(pp-to-string y))))))

(let UPATTERN EXPRESSION)

(pcase '(1 2 3)
  (`(1 2 ,(and foo (let 3 foo)))
   (message "A weird way of matching (1 2 3)")))

Fallback

(pcase-let (((or `(:key . ,val) (let val 42))
             (cons :key 123)))
  val)
(pcase-let (((or `(:key . ,val) (let val 42))
             nil))
  val)

pcase-dolist

(let (result)
  (pcase-dolist (`(,k . ,v) '((one . 1) (two . 2) (three . 3)))
    (push (list k v) result))
  result)

pcase-lambda

当函数参数是一个 List 时,用 pcase-lambda 能够在参数表里分解它,类似 pcase-let。

(funcall
 (pcase-lambda (`(,first ,second . ,rest))
   (message "(%s %s . %s)" first second rest))
 '(1 2 3 4 5))

(app FUN PAT)

(seq &rest ARGS)

Defined by seq.el so (require 'seq) is required before using it.

List, vector, string are all sequences.

(pcase "hello"
  ((seq first second) (string first second)))
(pcase [1 2 3]
  ((seq first second) (list first second)))

(rx &rest REGEXPS)

(pcase "  42  "
  ((rx (* blank) (let result (1+ (in "0-9"))) (* blank))
   result))
(pcase "a 1 2 3 3 2 1 b"
  ((rx (let x digit) space
       (let y digit) space
       (let z digit) space
       (backref z)   space
       (backref 2)   space
       (backref 1)   space)
   (list x y z)))

pcase-let

(pcase-let ((`(,_ ,two ,_ ,four) '(1 2 3 4)))
  (list two four))
(pcase-let ((`(,first . ,rest)
             (number-sequence 1 100)))
  (list first (apply #'+ rest)))
(pcase-let ((`(,a (,b (,c)))
             '(1 (2 (3)))))
  (list a b c))