From 32144f5ead60da494463f26709dbba0d70863188 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Thu, 29 Aug 2024 12:02:08 +0300 Subject: [PATCH] Document 'cond*' * doc/lispref/control.texi (cond* Macro): New subsection. Text written by Richard Stallman . * etc/NEWS: Document 'cond*'. (cherry picked from commit 38650b630bdb8b105a7e3c917cc8053133681abc) --- doc/lispref/control.texi | 140 +++++++++++++++++++++++++++++++++++++++ etc/NEWS | 9 +++ 2 files changed, 149 insertions(+) diff --git a/doc/lispref/control.texi b/doc/lispref/control.texi index 15393f1d7f7..d28505411df 100644 --- a/doc/lispref/control.texi +++ b/doc/lispref/control.texi @@ -537,6 +537,7 @@ sometimes ``the value matches the pattern''). * Extending @code{pcase}: Extending pcase. Define new kinds of patterns. * Backquote-Style Patterns: Backquote Patterns. Structural patterns matching. * Destructuring with pcase Patterns:: Using pcase patterns to extract subfields. +* The @code{cond*} macro: cond* Macro. Alternative to @code{pcase}. @end menu @node pcase Macro @@ -1409,6 +1410,145 @@ argument: @end example @end defmac +@node cond* Macro +@subsection The @code{pcase} macro +@findex cond*@r{, a macro} + + The @code{cond*} macro is an alternative to @code{pcase}, and supports +the same functionality, but using syntax that some might find less +cryptic. + +@defmac cond* &rest clauses +The @code{cond*} macro is an extended form of the traditional +@code{cond}. A @code{cond*} expression contains a series of +@var{clauses}, each of which can use @code{bind*} to specify binding +variables, use @code{match*} 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 @w{@code{(@var{condition} +@var{body}@dots{})}}. + +@var{condition} can be a Lisp expression, as in @code{cond} +(@pxref{Conditionals}). Or it can be @w{@code{(bind* +@var{bindings}@dots{})}} or @w{@code{(match* @var{pattern} +@var{datum})}}. + +@findex bind* +@code{(bind* @var{bindings}@dots{})} means to bind @var{bindings} (like +the bindings list in @code{let*}, @pxref{Local Variables}) for the body +of the clause. As a condition, it counts as true if the first binding's +value is non-@code{nil}. + +@findex match* +@code{(match* @var{pattern} @var{datum})} means to match @var{datum} +against the specified @var{pattern}. The condition counts as true if +@var{pattern} matches @var{datum}. The pattern can specify variables to +bind to the parts of @var{datum} that they match. + +Both @code{bind*} and @code{match*} normally bind their bindings over +the execution of the whole containing clause. However, if the clause is +written to specify ``non-exit'', the clause's bindings cover the whole +rest of the @code{cond*}. + +When a clause's condition is true, and it exits the @code{cond*} or is +the last clause, the value of the last expression in the clause's body +becomes the return value of the @code{cond*} construct. + +@subheading Non-exit clause + +If a clause has only one element, or if its first element is @code{t}, +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). The bindings made in @var{condition} for the +@var{body} of the non-exit clause are passed along to the rest of the +clauses in this @code{cond*} construct. + +@subheading Matching clauses + +A matching clause looks like @code{(match* @var{pattern} @var{datum})}. +It evaluates the expression @var{datum} and matches the pattern +@var{pattern} (which is not evaluated) against it. + +@var{pattern} allows these kinds of patterns, and those that are lists +often include other patters within them: + +@table @code +@item _ +Matches any value. +@item @var{keyword} +Matches that keyword. +@item nil +Matches @code{nil}. +@item t +Matches @code{t}. +@item @var{symbol} +Matches any value and binds @var{symbol} to that value. If @var{symbol} +has been matched and bound earlier in this pattern, it matches here the +same value that it matched before. +@item @var{regexp} +Matches a string if @var{regexp} matches it. The match must cover the +entire string from its first char to its last. +@item @var{atom} +(Meaning any other kind of non-list not described above.) Matches +anything `equal' to it. +@item (rx @var{regexp}) +Uses a regexp specified in s-expression form, as in the function +@code{rx} (@pxref{Rx Notation}, and matches the data that way. +@item (rx @var{regexp} @var{sym0} @var{sym1}@dots{}) +Uses a regexp specified in s-expression form, and binds the symbols +@var{sym0}, @var{sym1}, and so on to @w{@code{(match-string 0 +@var{datum})}}, @w{@code{(match-string 1 @var{datum})}}, and so on. You +can use as many @var{sym}s as regexp matching supports. +@item `@var{object} +Matches any value @code{equal} to @var{object}. +@item (cons @var{carpat} @code{cdrpat}) +Matches a cons cell if @var{carpat} matches its @code{car} and +@var{cdrpat} matches its @code{cdr}. +@item (list @var{eltpats}@dots{}) +Matches a list if the @var{eltpats} match its elements. The first +@var{eltpat} should match the list's first element. The second +@var{eltpat} should match the list's second element. And so on. +@item (vector @var{eltpats}@dots{}) +Matches a vector if the @var{eltpats} match its elements. The first +@var{eltpat} should match the vector's first element. The second +@var{eltpat} should match the vector's second element. And so on. +@item (cdr @var{pattern}) +Matches @var{pattern} with strict checking of @code{cdr}s. That means +that @code{list} patterns verify that the final @code{cdr} is +@code{nil}. Strict checking is the default. +@item (cdr-safe @var{pattern}) +Matches @var{pattern} with lax checking of @code{cdr}s. That means that +@code{list} patterns do not examine the final @code{cdr}. +@item (and @var{conjuncts}@dots{}) +Matches each of the @var{conjuncts} against the same data. If all of +them match, this pattern succeeds. If one @var{conjunct} fails, this +pattern fails and does not try more @var{conjuncts}. +@item (or @var{disjuncts}@dots{}) +Matches each of the @var{disjuncts} against the same data. If one +@var{disjunct} succeeds, this pattern succeeds and does not try more +@var{disjuncts}. If all of them fail, this pattern fails. +@item (@var{cond*-expander} @dots{}) +Here the @code{car} is a symbol that has a @code{cond*-expander} +property 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 its @code{car}). +The function should return an equivalent pattern to be matched instead. +@item (@var{predicate} @var{symbol}) +Matches datum if @code{(@var{predicate} @var{datum})} is true, then +binds @var{symbol} to @var{datum}. +@item (@var{predicate} @var{SYMBOL} @var{more-args}@dots{}) +Matches datum if @w{@code{(@var{predicate} @var{datum} +@var{more-args}@dots{})}} is true, then binds @var{symbol} to +@var{datum}. @var{more-args}@dots{} can refer to symbols bound earlier +in the pattern. +@item (constrain @var{symbol} @var{exp}) +Matches datum if the form @var{exp} is true. @var{exp} can refer to +symbols bound earlier in the pattern. +@end table + +@end defmac + @node Iteration @section Iteration @cindex iteration diff --git a/etc/NEWS b/etc/NEWS index adb297d251f..71deaf98446 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -291,6 +291,15 @@ This 'display' property was previously supported only as text property. Now overlays can also have this property, with the same effect for the text "covered" by the overlay. ++++ +** New macro 'cond*'. +The new macro 'cond*' is an alternative to 'pcase'. Like 'pcase', it +allows to define several clauses, each one of with its own condition; +the first clause that matches will cause its body to be evaluated. +'cond*' uses syntax that is different from that of 'pcase', which some +users might find less cryptic. See the Info node "(elisp) cond Macro" +for details. + * Changes in Emacs 31.1 on Non-Free Operating Systems -- 2.39.5