Up: Conditionals   [Contents][Index]

10.2.1 Pattern matching case statement

To compare a particular value against various possible cases, the macro pcase can come handy. It takes the following form:

(pcase exp branch1 branch2 branch3 …)

where each branch takes the form (upattern body-forms…).

It will first evaluate exp and then compare the value against each upattern to see which branch to use, after which it will run the corresponding body-forms. A common use case is to distinguish between a few different constant values:

(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 the last clause, code is a variable that gets bound to the value that was returned by (get-return-code x).

To give a more complex example, a simple interpreter for a little expression language could look like (note that this example requires 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))))

Where `(add ,x ,y) is a pattern that checks that exp is a three element list starting with the symbol add, then extracts the second and third elements and binds them to the variables x and y. (pred numberp) is a pattern that simply checks that exp is a number, and _ is the catch-all pattern that matches anything.

Here are some sample programs 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

There are two kinds of patterns involved in pcase, called U-patterns and Q-patterns. The upattern mentioned above are U-patterns and can take the following forms:

`qpattern

This is one of the most common form of patterns. The intention is to mimic the backquote macro: this pattern matches those values that could have been built by such a backquote expression. Since we’re pattern matching rather than building a value, the unquote does not indicate where to plug an expression, but instead it lets one specify a U-pattern that should match the value at that location.

More specifically, a Q-pattern can take the following forms:

(qpattern1 . qpattern2)

This pattern matches any cons cell whose car matches qpattern1 and whose cdr matches pattern2.

atom

This pattern matches any atom equal to atom.

,upattern

This pattern matches any object that matches the upattern.

symbol

A mere symbol in a U-pattern matches anything, and additionally let-binds this symbol to the value that it matched, so that you can later refer to it, either in the body-forms or also later in the pattern.

_

This so-called don’t care pattern matches anything, like the previous one, but unlike symbol patterns it does not bind any variable.

(pred pred)

This pattern matches if the function pred returns non-nil when called with the object being matched.

(or upattern1 upattern2…)

This pattern matches as soon as one of the argument patterns succeeds. All argument patterns should let-bind the same variables.

(and upattern1 upattern2…)

This pattern matches only if all the argument patterns succeed.

(guard exp)

This pattern ignores the object being examined and simply succeeds if exp evaluates to non-nil and fails otherwise. It is typically used inside an and pattern. For example, (and x (guard (< x 10))) is a pattern which matches any number smaller than 10 and let-binds it to the variable x.

Up: Conditionals   [Contents][Index]