Restore 'cond' one element clauses to 'cond*'

* lisp/emacs-lisp/cond-star.el (cond*-non-exit-clause-p)
(cond*-non-exit-clause-substance): Treat only one element
clauses beginning with match*/pcase* pseudoforms as non-exit.
(cond*-convert-condition): Handle exiting clauses with only one
element, that is a regular Lisp expression.
(cond*):
* doc/lispref/control.texi (cond* Macro): Document the change.
This commit is contained in:
Sean Whitton 2026-02-08 16:09:11 +00:00
parent e832976f1a
commit 2bf2855b57
2 changed files with 37 additions and 24 deletions

View file

@ -1549,8 +1549,9 @@ becomes the return value of the @code{cond*} construct.
@subheading Non-exit clauses
If a clause has only one element, or if its first element is @code{t} or
a @code{bind*} form, or if it ends with the keyword @code{:non-exit},
If the first element of a clause is @code{t} or a @code{bind*} form, or
if it has only one element and that element is a @code{match*} or
@code{pcase*} form, or if it ends with the keyword @code{:non-exit},
then this clause never exits the @code{cond*} construct. Instead,
control falls through to the next clause (if any). Except for a
@code{bind-and*} clause, the bindings made in @var{condition} for the

View file

@ -83,12 +83,13 @@ in its body becomes the return value of the `cond*' construct.
Non-exit clauses:
If a clause has only one element, or if its first element is t or a
`bind*' 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.
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."
@ -197,22 +198,31 @@ CONDITION of a `cond*' clause. See `cond*' for details."
(defun cond*-non-exit-clause-p (clause)
"If CLAUSE, a cond* clause, is a non-exit clause, return t."
(or (null (cdr-safe clause)) ;; clause has only one element.
(and (cdr-safe clause)
;; Starts with t.
(or (eq (car clause) t)
;; Starts with a `bind*' pseudo-form.
(and (consp (car clause))
(eq (caar clause) 'bind*))))
;; Ends with keyword.
(eq (car (last clause)) :non-exit)))
(or
;; Starts with t.
(and (cdr-safe clause)
(eq (car clause) t))
;; Starts with a `bind*' pseudo-form.
(and (consp (car clause))
(eq (caar clause) 'bind*))
;; Has one element that's a `match*' or `pcase*' pseudo-form.
(and (null (cdr-safe clause))
(consp (car clause))
(memq (caar clause) '(match* pcase*)))
;; Ends with keyword.
(eq (car (last clause)) :non-exit)))
(defun cond*-non-exit-clause-substance (clause)
"For a non-exit cond* clause CLAUSE, return its substance.
This removes a final keyword if that's what makes CLAUSE non-exit."
(cond ((or (null (cdr-safe clause)) ;; either clause has only one element
(and (consp (car clause)) ;; or it starts with `bind*'
(eq (caar clause) 'bind*)))
(cond ((or
;; Starts with `bind*' pseudo-form.
(and (consp (car clause))
(eq (caar clause) 'bind*))
;; Or has one element that's a `match*'/`pcase*' pseudo-form.
(and (null (cdr-safe clause))
(consp (car clause))
(memq (caar clause) '(match* pcase*))))
clause)
;; Starts with t or a keyword.
;; Include t as the first element of the substance
@ -374,12 +384,14 @@ This is used for conditional exit clauses."
;; Ordinary Lisp expression is the condition.
(if rest
;; A nonfinal exiting clause.
;; If condition succeeds, run the TRUE-EXPS.
;; If condition succeeds, return it or run the TRUE-EXPS.
;; There are following clauses, so run IFFALSE
;; if the condition fails.
`(if ,condition
(progn . ,true-exps)
,iffalse)
(if true-exps
`(if ,condition
(progn . ,true-exps)
,iffalse)
`(or ,condition ,iffalse))
(if uncondit-clauses
;; A non-exit clause.
;; If condition succeeds, run the TRUE-EXPS.