Up: Conditionals [Contents][Index]
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…)
.
pcase
tries to match the value of expression to the
pattern of each clause, in textual order. If the value matches,
the clause succeeds; pcase
then 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 equal
to 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.
(pred predfun)
Matches if the predicate function predfun returns non-nil
when called with the value being matched as its argument.
predfun can be one of the possible forms described below.
(guard boolean-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 an and
UPattern, see
below. For example, (and x (guard (< x 10)))
is a pattern
which matches any number smaller than 10 and let-binds the variable
x
to that number.
(let upattern 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 called let
because
upattern can bind symbols to values using the symbol
UPattern. For example:
((or `(key . ,val) (let val 5)) val)
.)
(app function upattern)
Matches if function applied to the value being matched returns a
value that matches upattern. This is like the pred
UPattern, 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.
(or upattern1 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.
(and upattern1 upattern2…)
Matches if all the argument UPatterns match.
The function calls used in the pred
and app
UPatterns
can have one of the following forms:
integerp
In this case, the named function is applied to the value being matched.
(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 pcase
against 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 car
matches qpattern1 and whose cdr
matches qpattern2.
This readily generalizes to backquoted lists as in
(qpattern1 qpattern2 …)
.
[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
equal
to 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.
Up: Conditionals [Contents][Index]