Function: pcase
pcase is an autoloaded macro defined in pcase.el.gz.
Signature
(pcase EXP &rest CASES)
Documentation
Evaluate EXP to get EXPVAL; try passing control to one of CASES.
CASES is a list of elements of the form (PATTERN CODE...). For the first CASE whose PATTERN "matches" EXPVAL, evaluate its CODE..., and return the value of the last form. If no CASE has a PATTERN that matches, return nil.
Each PATTERN expands, in essence, to a predicate to call on EXPVAL. When the return value of that call is non-nil, PATTERN matches. PATTERN can take one of the forms:
_ matches anything.
'VAL matches if EXPVAL is equal to VAL.
KEYWORD shorthand for 'KEYWORD
INTEGER shorthand for 'INTEGER
STRING shorthand for 'STRING
SYMBOL matches anything and binds it to SYMBOL.
If a SYMBOL is used twice in the same pattern
the second occurrence becomes an equality test.
(pred FUN) matches if FUN called on EXPVAL returns non-nil.
(pred (not FUN)) matches if FUN called on EXPVAL returns nil.
(app FUN PAT) matches if FUN called on EXPVAL matches PAT.
(guard BOOLEXP) matches if BOOLEXP evaluates to non-nil.
(and PAT...) matches if all the patterns match.
(or PAT...) matches if any of the patterns matches.
FUN in pred and app can take one of the forms:
SYMBOL or (lambda ARGS BODY)
call it with one argument
(F ARG1 .. ARGn)
call F with ARG1..ARGn and EXPVAL as n+1'th argument
FUN, BOOLEXP, and subsequent PAT can refer to variables bound earlier in the pattern by a SYMBOL pattern.
Additional patterns can be defined using pcase-defmacro.
See Info node (elisp) Pattern-Matching Conditional in the Emacs Lisp manual for more information and examples.
-- `QPAT
Backquote-style pcase patterns: `QPAT
QPAT can take the following forms:
(QPAT1 . QPAT2) matches if QPAT1 matches the car and QPAT2 the cdr.
[QPAT1 QPAT2..QPATn] matches a vector of length n and QPAT1..QPATn match
its 0..(n-1)th elements, respectively.
,PAT matches if the pcase pattern PAT matches.
SYMBOL matches if EXPVAL is equal to SYMBOL.
KEYWORD likewise for KEYWORD.
NUMBER likewise for NUMBER.
STRING likewise for STRING.
The list or vector QPAT is a template. The predicate formed by a backquote-style pattern is a combination of those formed by any sub-patterns, wrapped in a top-level condition: EXPVAL must be "congruent" with the template. For example:
`(technical ,forum)
The predicate is the logical-AND of:
- Is EXPVAL a list of two elements?
- Is the first element the symbol technical?
- True! (The second element can be anything, and for the sake
of the body forms, its value is bound to the symbol forum.)
-- (rx &rest REGEXPS)
A pattern that matches strings against rx REGEXPS in sexp form.
REGEXPS are interpreted as in rx. The pattern matches any
string that is a match for REGEXPS, as if by string-match.
In addition to the usual rx syntax, REGEXPS can contain the
following constructs:
(let REF RX...) binds the symbol REF to a submatch that matches
the regular expressions RX. REF is bound in
CODE to the string of the submatch or nil, but
can also be used in backref.
(backref REF) matches whatever the submatch REF matched.
REF can be a number, as usual, or a name
introduced by a previous (let REF ...)
construct.
-- (eieio &rest FIELDS)
Pcase patterns that match EIEIO object EXPVAL.
Elements of FIELDS can be of the form (NAME PAT) in which case the
contents of field NAME is matched against PAT, or they can be of
the form NAME which is a shorthand for (NAME NAME).
-- (let PAT EXPR)
Matches if EXPR matches PAT.
-- (map &rest ARGS)
Build a pcase pattern matching map elements.
ARGS is a list of elements to be matched in the map.
Each element of ARGS can be of the form (KEY PAT), in which case KEY is evaluated and searched for in the map. The match fails if for any KEY found in the map, the corresponding PAT doesn't match the value associated with the KEY.
Each element can also be a SYMBOL, which is an abbreviation of a (KEY PAT) tuple of the form ('SYMBOL SYMBOL). When SYMBOL is a keyword, it is an abbreviation of the form (:SYMBOL SYMBOL), useful for binding plist values.
Keys in ARGS not found in the map are ignored, and the match doesn't fail.
-- (seq &rest PATTERNS)
Build a pcase pattern that matches elements of SEQUENCE.
The pcase pattern will match each element of PATTERNS against the
corresponding element of SEQUENCE.
Extra elements of the sequence are ignored if fewer PATTERNS are given, and the match does not fail.
-- (radix-tree-leaf VPAT)
Pattern which matches a radix-tree leaf. The pattern VPAT is matched against the leaf's carried value.
-- (cl-struct TYPE &rest FIELDS)
Pcase patterns that match cl-struct EXPVAL of type TYPE. Elements of FIELDS can be of the form (NAME PAT) in which case the contents of field NAME is matched against PAT, or they can be of the form NAME which is a shorthand for (NAME NAME).
-- (cl-type TYPE)
Pcase pattern that matches objects of TYPE.
TYPE is a type descriptor as accepted by cl-typep, which see.
Probably introduced at or before Emacs version 24.1.
Source Code
;; Defined in /usr/src/emacs/lisp/emacs-lisp/pcase.el.gz
;;;###autoload
(defmacro pcase (exp &rest cases)
;; FIXME: Add some "global pattern" to wrap every case?
;; Could be used to wrap all cases in a `
"Evaluate EXP to get EXPVAL; try passing control to one of CASES.
CASES is a list of elements of the form (PATTERN CODE...).
For the first CASE whose PATTERN \"matches\" EXPVAL,
evaluate its CODE..., and return the value of the last form.
If no CASE has a PATTERN that matches, return nil.
Each PATTERN expands, in essence, to a predicate to call
on EXPVAL. When the return value of that call is non-nil,
PATTERN matches. PATTERN can take one of the forms:
_ matches anything.
\\='VAL matches if EXPVAL is `equal' to VAL.
KEYWORD shorthand for \\='KEYWORD
INTEGER shorthand for \\='INTEGER
STRING shorthand for \\='STRING
SYMBOL matches anything and binds it to SYMBOL.
If a SYMBOL is used twice in the same pattern
the second occurrence becomes an `eq'uality test.
(pred FUN) matches if FUN called on EXPVAL returns non-nil.
(pred (not FUN)) matches if FUN called on EXPVAL returns nil.
(app FUN PAT) matches if FUN called on EXPVAL matches PAT.
(guard BOOLEXP) matches if BOOLEXP evaluates to non-nil.
(and PAT...) matches if all the patterns match.
(or PAT...) matches if any of the patterns matches.
FUN in `pred' and `app' can take one of the forms:
SYMBOL or (lambda ARGS BODY)
call it with one argument
(F ARG1 .. ARGn)
call F with ARG1..ARGn and EXPVAL as n+1'th argument
FUN, BOOLEXP, and subsequent PAT can refer to variables
bound earlier in the pattern by a SYMBOL pattern.
Additional patterns can be defined using `pcase-defmacro'.
See Info node `(elisp) Pattern-Matching Conditional' in the
Emacs Lisp manual for more information and examples."
(declare (indent 1) (debug (form &rest (pcase-PAT body))))
;; We want to use a weak hash table as a cache, but the key will unavoidably
;; be based on `exp' and `cases', yet `cases' is a fresh new list each time
;; we're called so it'll be immediately GC'd. So we use (car cases) as key
;; which does come straight from the source code and should hence not be GC'd
;; so easily.
(let ((data (gethash (car cases) pcase--memoize)))
;; data = (EXP CASES . EXPANSION)
(if (and (equal exp (car data)) (equal cases (cadr data)))
;; We have the right expansion.
(cddr data)
;; (when (gethash (car cases) pcase--memoize-1)
;; (message "pcase-memoize failed because of weak key!!"))
;; (when (gethash (car cases) pcase--memoize-2)
;; (message "pcase-memoize failed because of eq test on %S"
;; (car cases)))
;; (when data
;; (message "pcase-memoize: equal first branch, yet different"))
(let ((expansion (pcase--expand exp cases)))
(puthash (car cases) `(,exp ,cases ,@expansion) pcase--memoize)
;; (puthash (car cases) `(,exp ,cases ,@expansion) pcase--memoize-1)
;; (puthash (car cases) `(,exp ,cases ,@expansion) pcase--memoize-2)
expansion))))