Up: Conditionals   [Contents][Index]

10.2.1 Pattern matching case statement

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.

Macro: pcase expression &rest clauses

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:

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 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 qpattern2qpatternm]

Matches if the value being matched is a vector of length m whose 0..(m-1)th elements match qpattern1, qpattern2qpatternm, 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.

Macro: pcase-defmacro name args &rest body

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]