gnu.org (original) (raw)
11.4.4 Destructuring with pcase
Patterns
Pcase patterns not only express a condition on the form of the objects they can match, but they can also extract sub-fields of those objects. For example we can extract 2 elements from a list that is the value of the variable my-list
with the following code:
(pcase my-list (`(add ,x ,y) (message "Contains %S and %S" x y)))
This will not only extract x
and y
but will additionally test that my-list
is a list containing exactly 3 elements and whose first element is the symbol add
. If any of those tests fail, pcase
will immediately return nil
without callingmessage
.
Extraction of multiple values stored in an object is known as_destructuring_. Using pcase
patterns allows you to perform destructuring binding, which is similar to a local binding (see Local Variables), but gives values to multiple elements of a variable by extracting those values from an object of compatible structure.
The macros described in this section use pcase
patterns to perform destructuring binding. The condition of the object to be of compatible structure means that the object must match the pattern, because only then the object’s subfields can be extracted. For example:
(pcase-let ((`(add ,x ,y) my-list)) (message "Contains %S and %S" x y))
does the same as the previous example, except that it directly tries to extract x
and y
from my-list
without first verifying if my-list
is a list which has the right number of elements and has add
as its first element.
The precise behavior when the object does not actually match the pattern depends on the types, although the body will not be silently skipped: either an error is signaled or the body is run with some of the variables bound to arbitrary values like nil
. For example, the above pattern will result in x and ybeing extracted with operations like car
or nth
, so they will get value nil
when my-list is too short. In contrast, with a pattern like `[add ,x ,y]
, those same variables would be extracted using aref
which would signal an error ifmy-list is not an array or is too short.
The pcase patterns that are useful for destructuring bindings are generally those described in Backquote-Style Patterns, since they express a specification of the structure of objects that will match.
For an alternative facility for destructuring binding, seeseq-let.
Macro: pcase-let bindings body… ¶
Perform destructuring binding of variables according tobindings, and then evaluate body.
bindings is a list of bindings of the form (pattern exp)
, where exp is an expression to evaluate andpattern is a pcase
pattern.
All exps are evaluated first, after which they are matched against their respective pattern, introducing new variable bindings that can then be used inside body. The variable bindings are produced by destructuring binding of elements ofpattern to the values of the corresponding elements of the evaluated exp.
Here’s a trivial example:
(pcase-let ((`(,major ,minor) (split-string "image/png" "/"))) minor) ⇒ "png"
Macro: pcase-let* bindings body… ¶
Perform destructuring binding of variables according tobindings, and then evaluate body.
bindings is a list of bindings of the form (pattern exp)
, where exp is an expression to evaluate andpattern is a pcase
pattern. The variable bindings are produced by destructuring binding of elements of pattern to the values of the corresponding elements of the evaluated exp.
Unlike pcase-let
, but similarly to let*
, each expis matched against its corresponding pattern before processing the next element of bindings, so the variable bindings introduced in each one of the bindings are available in theexps of the bindings that follow it, additionally to being available in body.
Macro: pcase-dolist (pattern list) body… ¶
Execute body once for each element of list, on each iteration performing a destructuring binding of variables inpattern to the values of the corresponding subfields of the element of list. The bindings are performed as if bypcase-let
. When pattern is a simple variable, this ends up being equivalent to dolist
(see Iteration).
Macro: pcase-setq pattern value… ¶
Assign values to variables in a setq
form, destructuring eachvalue according to its respective pattern.
Macro: pcase-lambda lambda-list &rest body ¶
This is like lambda
, but allows each argument to be a pattern. For instance, here’s a simple function that takes a cons cell as the argument:
(setq fun (pcase-lambda (`(,key . ,val)) (vector key (* val 10)))) (funcall fun '(foo . 2)) ⇒ [foo 20]