Function: cond*

cond* is an autoloaded macro defined in cond-star.el.gz.

Signature

(cond* &rest CLAUSES)

Documentation

Extended form of traditional Lisp cond construct.

A cond* construct is a series of clauses, and a clause normally has the form (CONDITION BODY...).

CONDITION can be a Lisp expression, as in cond. Or it can be one of (bind* BINDINGS...), (match* PATTERN DATUM),
(bind-and* BINDINGS...) or (pcase* PATTERN DATUM),

(bind* BINDINGS...) means to bind BINDINGS (as if they were in let*)
for the body of the clause, and all subsequent clauses, since the bind* clause is always a non-exit clause. As a condition, it counts as true and runs the body of the clause if the first binding's value is non-nil.

(match* PATTERN DATUM) means to match DATUM against the pattern PATTERN
For its patterns, see match*. The condition counts as true if PATTERN matches DATUM.

(bind-and* BINDINGS...) means to bind BINDINGS (as if they were in
if-let*) for only the the body of the clause. If any expression evaluates to nil, the condition counts as false.

(pcase* PATTERN DATUM) means to match DATUM against the
pattern PATTERN, using the same pattern syntax as pcase. The condition counts as true if PATTERN matches DATUM.

When a clause's condition is true, and it exits the cond* or is the last clause, the value of the last expression in its body becomes the return value of the cond* construct.

Non-exit clauses:

If the first element of a clause is t or a bind* form, or if it has only one element and that element is a match* or pcase* form, or if it ends with the keyword :non-exit, then this clause never exits the cond* construct. Instead, control always falls through to the next clause (if any). Except for a bind-and* clause, all bindings made in CONDITION for the BODY of the non-exit clause are passed along to the rest of the clauses in this cond* construct.

See match* for documentation of the patterns for use in match* conditions.

View in manual

Probably introduced at or before Emacs version 31.1.

Source Code

;; Defined in /usr/src/emacs/lisp/emacs-lisp/cond-star.el.gz
;;; cond-star.el --- Extended form of `cond' construct  -*-lexical-binding: t; -*-

;; Copyright (C) 2024-2026 Free Software Foundation, Inc.

;; Maintainer: Richard Stallman <rms@gnu.org>
;; Package: cond-star
;; Version: 1.0
;; Package-Requires: ((emacs "24.3"))

;; This is a GNU ELPA :core package.  Avoid functionality that is not
;; compatible with the version of Emacs recorded above.

;; This file is part of GNU Emacs.

;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.

;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.

;;; Commentary:

;; This library implements the `cond*' macro, that extends `cond' with
;; pattern-matching capabilities.  It provides an alternative to
;; `pcase'.  Consult the Info note `(elisp) cond* Macro' for details on
;; how to use it.

;;; Implementation Notice:

;; Here is the list of functions the generated code is known to call:
;; car, cdr, car-safe, cdr-safe, nth, nthcdr, null, eq, equal, eql, =,
;; vectorp, length.
;; It also uses these control and binding primitives:
;; and, or, if, progn, let, let*, setq.
;; For regexp matching only, it can call string-match and match-string.

;; ??? If a clause starts with a keyword,
;; should the element after the keyword be treated in the usual way
;; as a pattern?  Currently `cond*-non-exit-clause-substance' explicitly
;; prevents that by adding t at the front of its value.

;;; Code:

;;;###autoload
(defmacro cond* (&rest clauses)
  "Extended form of traditional Lisp `cond' construct.
A `cond*' construct is a series of clauses, and a clause
normally has the form (CONDITION BODY...).

CONDITION can be a Lisp expression, as in `cond'.
Or it can be one of `(bind* BINDINGS...)', `(match* PATTERN DATUM)',
`(bind-and* BINDINGS...)' or `(pcase* PATTERN DATUM)',

`(bind* BINDINGS...)' means to bind BINDINGS (as if they were in `let*')
for the body of the clause, and all subsequent clauses, since the `bind*'
clause is always a non-exit clause.  As a condition, it counts as true
and runs the body of the clause if the first binding's value is non-nil.

`(match* PATTERN DATUM)' means to match DATUM against the pattern PATTERN
For its patterns, see `match*'.
The condition counts as true if PATTERN matches DATUM.

`(bind-and* BINDINGS...)' means to bind BINDINGS (as if they were in
`if-let*') for only the the body of the clause.  If any expression
evaluates to nil, the condition counts as false.

`(pcase* PATTERN DATUM)' means to match DATUM against the
pattern PATTERN, using the same pattern syntax as `pcase'.
The condition counts as true if PATTERN matches DATUM.

When a clause's condition is true, and it exits the `cond*'
or is the last clause, the value of the last expression
in its body becomes the return value of the `cond*' construct.

Non-exit clauses:

If the first element of a clause is t or a `bind*' form, or if it has
only one element and that element is a `match*' or `pcase*' form, or if
it ends with the keyword `:non-exit', then this clause never exits the
`cond*' construct.  Instead, control always falls through to the next
clause (if any).  Except for a `bind-and*' clause, all bindings made in
CONDITION for the BODY of the non-exit clause are passed along to the
rest of the clauses in this `cond*' construct.

See `match*' for documentation of the patterns for use in `match*'
conditions."
  (declare
   (debug (&rest ([&or ("bind*" &rest &or symbolp (symbolp &optional form))
                       ("bind-and*" &rest &or symbolp (symbolp form) (form))
                       ("match*" sexp form)
                       ("pcase*" pcase-PAT form)
                       form]
                  body))))
  (cond*-convert clauses))