Up: Conditionals
The cond form lets you choose between alternatives using
predicate conditions that compare values of expressions against
specific values known and written in advance. However, sometimes it
is useful to select alternatives based on more general conditions that
distinguish between broad classes of values. The pcase macro
allows you to choose between alternatives based on matching the value
of an expression against a series of patterns. A pattern can be a
literal value (for comparisons to literal values you'd use
cond), or it can be a more general description of the expected
structure of the expression's value.
Evaluate expression and choose among an arbitrary number of alternatives based on the value of expression. The possible alternatives are specified by clauses, each of which must be a list of the form
(pattern body-forms...).pcasetries to match the value of expression to the pattern of each clause, in textual order. If the value matches, the clause succeeds;pcasethen evaluates its body-forms, and returns the value of the last of body-forms. Any remaining clauses are ignored.The pattern part of a clause can be of one of two types: QPattern, a pattern quoted with a backquote; or a UPattern, which is not quoted. UPatterns are simpler, so we describe them first.
Note: In the description of the patterns below, we use “the value being matched” to refer to the value of the expression that is the first argument of
pcase.A UPattern can have the following forms:
'val- Matches if the value being matched is
equalto val.- atom
- Matches any atom, which can be a keyword, a number, or a string. (These are self-quoting, so this kind of UPattern is actually a shorthand for
'atom.) Note that a string or a float matches any string or float with the same contents/value._- Matches any value. This is known as don't care or wildcard.
- symbol
- Matches any value, and additionally let-binds symbol to the value it matched, so that you can later refer to it, either in the body-forms or also later in the pattern.
(predpredfun)- Matches if the predicate function predfun returns non-
nilwhen called with the value being matched as its argument. predfun can be one of the possible forms described below.(guardboolean-expression)- Matches if boolean-expression evaluates to non-
nil. This allows you to include in a UPattern boolean conditions that refer to symbols bound to values (including the value being matched) by previous UPatterns. Typically used inside anandUPattern, see below. For example,(and x (guard (< x 10)))is a pattern which matches any number smaller than 10 and let-binds the variablexto that number.(letupattern expression)- Matches if the specified expression matches the specified upattern. This allows matching a pattern against the value of an arbitrary expression, not just the expression that is the first argument to
pcase. (It is calledletbecause upattern can bind symbols to values using the symbol UPattern. For example:((or `(key . ,val) (let val 5)) val).)(appfunction upattern)- Matches if function applied to the value being matched returns a value that matches upattern. This is like the
predUPattern, except that it tests the result against upattern, rather than against a boolean truth value. The function call can use one of the forms described below.(orupattern1 upattern2...)- Matches if one the argument UPatterns matches. As soon as the first matching UPattern is found, the rest are not tested. For this reason, if any of the UPatterns let-bind symbols to the matched value, they should all bind the same symbols.
(andupattern1 upattern2...)- Matches if all the argument UPatterns match.
The function calls used in the
predandappUPatterns can have one of the following forms:
- function symbol, like
integerp- In this case, the named function is applied to the value being matched.
- lambda-function
(lambda (arg)body)- In this case, the lambda-function is called with one argument, the value being matched.
(func args...)- This is a function call with n specified arguments; the function is called with these n arguments and an additional n+1-th argument that is the value being matched.
Here's an illustrative example of using UPatterns:
(pcase (get-return-code x) ('success (message "Done!")) ('would-block (message "Sorry, can't do it now")) ('read-only (message "The shmliblick is read-only")) ('access-denied (message "You do not have the needed rights")) (code (message "Unknown return code %S" code)))In addition, you can use backquoted patterns that are more powerful. They allow matching the value of the expression that is the first argument of
pcaseagainst specifications of its structure. For example, you can specify that the value must be a list of 2 elements whose first element is a specific string and the second element is any value with a backquoted pattern like`("first" ,second-elem).Backquoted patterns have the form
`qpattern where qpattern can have the following forms:
(qpattern1.qpattern2)- Matches if the value being matched is a cons cell whose
carmatches qpattern1 and whosecdrmatches qpattern2. This readily generalizes to backquoted lists as in(qpattern1qpattern2...).[qpattern1 qpattern2...qpatternm]- Matches if the value being matched is a vector of length m whose
0..(m-1)th elements match qpattern1, qpattern2 ... qpatternm, respectively.- atom
- Matches if corresponding element of the value being matched is
equalto the specified atom.,upattern- Matches if the corresponding element of the value being matched matches the specified upattern.
Note that uses of QPatterns can be expressed using only UPatterns, as QPatterns are implemented on top of UPatterns using
pcase-defmacro, described below. However, using QPatterns will in many cases lead to a more readable code.
Here is an example of using pcase to implement a simple
interpreter for a little expression language (note that this example
requires lexical binding, see Lexical Binding):
(defun evaluate (exp env)
(pcase exp
(`(add ,x ,y) (+ (evaluate x env) (evaluate y env)))
(`(call ,fun ,arg) (funcall (evaluate fun env) (evaluate arg env)))
(`(fn ,arg ,body) (lambda (val)
(evaluate body (cons (cons arg val) env))))
((pred numberp) exp)
((pred symbolp) (cdr (assq exp env)))
(_ (error "Unknown expression %S" exp))))
Here `(add ,x ,y) is a pattern that checks that exp is a
three-element list starting with the literal symbol add, then
extracts the second and third elements and binds them to the variables
x and y. Then it evaluates x and y and
adds the results. The call and fn patterns similarly
implement two flavors of function calls. (pred numberp) is a
pattern that simply checks that exp is a number and if so,
evaluates it. (pred symbolp) matches symbols, and returns
their association. Finally, _ is the catch-all pattern that
matches anything, so it's suitable for reporting syntax errors.
Here are some sample programs in this small language, including their evaluation results:
(evaluate '(add 1 2) nil) ;=> 3
(evaluate '(add x y) '((x . 1) (y . 2))) ;=> 3
(evaluate '(call (fn x (add 1 x)) 2) nil) ;=> 3
(evaluate '(sub 1 2) nil) ;=> error
Additional UPatterns can be defined using the pcase-defmacro
macro.
Define a new kind of UPattern for
pcase. The new UPattern will be invoked as(name actual-args). The body should describe how to rewrite the UPattern name into some other UPattern. The rewriting will be the result of evaluating body in an environment where args are bound to actual-args.