@end group
@end example
+If can be convenient to bind variables in conjunction with using a
+conditional. It's often the case that you do a computation, and then
+want to do something with that computation if it's non-@code{nil}.
+The straightforward way to do that is to just write, for instance:
+
+@example
+(let ((result1 (do-computation)))
+ (when result1
+ (let ((result2 (do-more result1)))
+ (when result2
+ (do-something result2)))))
+@end example
+
+Since this is a very common pattern, Emacs provides a number of macros
+to make this easier and more readable. The above can be written the
+following way instead:
+
+@example
+(when-let ((result1 (do-computation))
+ (result2 (do-more result1)))
+ (do-something result2))
+@end example
+
+There's a number of variations on this theme, and they're briefly
+described below.
+
+@defmac if-let spec then-form else-forms...
+Evaluate each binding in @var{spec} in turn, like in @code{let*}
+(@pxref{Local Variables}, stopping if a binding value is @code{nil}.
+If all are non-@code{nil}, return the value of @var{then-form},
+otherwise the last form in @var{else-forms}.
+@end defmac
+
+@defmac when-let spec then-forms...
+Like @code{if-let}, but without @var{else-forms}.
+@end defmac
+
+@defmac while-let spec then-forms...
+Like @code{when-let}, but repeat until a binding in @var{spec} is
+@code{nil}. The return value is always @code{nil}.
+@end defmac
+
@node Combining Conditions
@section Constructs for Combining Conditions
@cindex combining conditions
\f
* Lisp Changes in Emacs 29.1
++++
+** New macro 'while-let'.
+This is like 'when-let', but repeats until a binding form is nil.
+
+++
** New function 'make-obsolete-generalized-variable'.
This can be used to mark setters used by 'setf' as obsolete, and the
(declare (indent 1) (debug if-let))
(list 'if-let spec (macroexp-progn body)))
+(defmacro while-let (spec &rest body)
+ "Bind variables according to SPEC and conditionally evaluate BODY.
+Evaluate each binding in turn, stopping if a binding value is nil.
+If all bindings are non-nil, eval BODY and repeat.
+The variable list SPEC is the same as in `if-let'."
+ (declare (indent 1) (debug if-let))
+ (let ((done (gensym "done")))
+ `(catch ',done
+ (while t
+ (if-let ,spec
+ (progn
+ ,@body)
+ (throw ',done nil))))))
;; PUBLIC: find if the current mode derives from another.