The cond* macro
You can use the cond* macro as an alternative to pcase if you find pcase’s syntax too cryptic. In addition, cond* offers some new forms of control flow that aren’t related to being an alternative to pcase.
- Macro: cond* &rest clauses
-
The
cond*macro is an extended form of the traditionalcond. Acond*expression contains a series of clauses, each of which can usebind*orbind-and*to specify binding variables, usematch*orpcase*to specify matching a pattern as a condition, or specify an expression as a condition to evaluate as a test.Each clause normally has the form
(condition body…).condition can be a Lisp expression, as in
cond(see Conditionals). Or it can be(bind* bindings…),(match* pattern datum),(bind-and* bindings…)or(pcase* pattern datum)(bind* bindings…)means to bind bindings (like the bindings list inlet*, see Local Variables) for the body of the clause, and all subsequent clauses. As a condition, it counts as true if the first binding’s value is non-nil.(bind-and* bindings…)means to bind bindings (like the bindings list inif-let*, see Conditionals) for only the body of the clause. As a condition, it counts as true if none of the bindings evaluate tonil. In addition, if any binding evaluates tonil, the expressions for the values of subsequent bindings are not evaluated.(match* pattern datum)means to match datum against the specified pattern. The condition counts as true if pattern matches datum. The pattern can specify variables to bind to the parts of datum that they match.(pcase* pattern datum)works in the same way except it uses the Pcase syntax for pattern.match*, andpcase*normally bind their bindings over the execution of the whole containing clause. However, if the clause is written to specify “non-exit” (see below), the clause’s bindings cover the whole rest of thecond*.When a clause’s condition is true, and it exits the
cond*or is the last clause, the value of the last expression in the clause’s body becomes the return value of thecond*construct.Non-exit clauses
If the first element of a clause is
tor abind*form, or if it has only one element and that element is amatch*orpcase*form, or if it ends with the keyword:non-exit, then this clause never exits thecond*construct. Instead, control falls through to the next clause (if any). Except for abind-and*clause, the bindings made in condition for the body of the non-exit clause are passed along to the rest of the clauses in thiscond*construct.Note:
pcase*does not support:non-exit, and when used in a non-exit clause, it follows the semantics ofpcase-let, see Destructuring withpcasePatterns.Matching clauses
A matching clause looks like
(match* pattern datum). It evaluates the expression datum and matches the pattern pattern (which is not evaluated) against it.pattern allows these kinds of patterns, and those that are lists often include other patterns within them:
_Matches any value.
keywordMatches that keyword.
nilMatches
nil.tMatches
t.symbolMatches any value and binds symbol to that value. If symbol has been matched and bound earlier in this pattern, it matches here the same value that it matched before.
regexpMatches a string if regexp matches it. The match must cover the entire string from its first char to its last.
atom(Meaning any other kind of non-list not described above.) Matches anything ‘equal’ to it.
(rx regexp)Uses a regexp specified in s-expression form, as in the function
rx(see TherxStructured Regexp Notation, and matches the data that way.(rx regexp sym0 sym1…)Uses a regexp specified in s-expression form, and binds the symbols sym0, sym1, and so on to
(match-string 0 datum),(match-string 1 datum), and so on. You can use as many syms as regexp matching supports.`objectMatches any value
equalto object.(cons carpatcdrpat)Matches a cons cell if carpat matches its
carand cdrpat matches itscdr.(list eltpats…)Matches a list if the eltpats match its elements. The first eltpat should match the list’s first element. The second eltpat should match the list’s second element. And so on.
(vector eltpats…)Matches a vector if the eltpats match its elements. The first eltpat should match the vector’s first element. The second eltpat should match the vector’s second element. And so on.
(cdr pattern)Matches pattern with strict checking of
cdrs. That means thatlistpatterns verify that the finalcdrisnil. Strict checking is the default.(cdr-ignore pattern)Matches pattern with lax checking of
cdrs. That means thatlistpatterns do not examine the finalcdr.(and conjuncts…)Matches each of the conjuncts against the same data. If all of them match, this pattern succeeds. If one conjunct fails, this pattern fails and does not try more conjuncts.
(or disjuncts…)Matches each of the disjuncts against the same data. If one disjunct succeeds, this pattern succeeds and does not try more disjuncts. If all of them fail, this pattern fails.
(cond*-expander …)Here the
caris a symbol that has acond*-expanderproperty which defines how to handle it in a pattern. The property value is a function. Trying to match such a pattern calls that function with one argument, the pattern in question (including itscar). The function should return an equivalent pattern to be matched instead.(predicate symbol)Matches datum if
(predicate datum)is true, then binds symbol to datum.(predicate SYMBOL more-args…)Matches datum if
(predicate datum more-args…)is true, then binds symbol to datum. more-args… can refer to symbols bound earlier in the pattern.(constrain symbol exp)Matches datum if the form exp is true. exp can refer to symbols bound earlier in the pattern.
Copyright © 1990-1996, 1998-2026 Free Software Foundation, Inc.
Licensed under the GNU GPL license.
https://www.gnu.org/software/emacs/manual/html_node/elisp/cond_002a-Macro.html