Next: Constructs for Combining Conditions, Previous: Sequencing, Up: Control Structures [Contents][Index]
11.2 ConditionalsConditional control structures choose among alternatives. Emacs Lisp has five conditional forms: if
, which is much the same as in other languages; when
and unless
, which are variants of if
; cond
, which is a generalized case statement; and pcase
, which is a generalization of cond
(see Pattern-Matching Conditional).
if
chooses between the then-form and the else-forms based on the value of condition. If the evaluated condition is non-nil
, then-form is evaluated and the result returned. Otherwise, the else-forms are evaluated in textual order, and the value of the last one is returned. (The else part of if
is an example of an implicit progn
. See Sequencing.)
If condition has the value nil
, and no else-forms are given, if
returns nil
.
if
is a special form because the branch that is not selected is never evaluated—it is ignored. Thus, in this example, true
is not printed because print
is never called:
(if nil (print 'true) 'very-false) ⇒ very-false
This is a variant of if
where there are no else-forms, and possibly several then-forms. In particular,
is entirely equivalent to
(if condition (progn a b c) nil)
This is a variant of if
where there is no then-form:
is entirely equivalent to
cond
chooses among an arbitrary number of alternatives. Each clause in the cond
must be a list. The CAR of this list is the condition; the remaining elements, if any, the body-forms. Thus, a clause looks like this:
cond
tries the clauses in textual order, by evaluating the condition of each clause. If the value of condition is non-nil
, the clause succeeds; then cond
evaluates its body-forms, and returns the value of the last of body-forms. Any remaining clauses are ignored.
If the value of condition is nil
, the clause fails, so the cond
moves on to the following clause, trying its condition.
A clause may also look like this:
Then, if condition is non-nil
when tested, the cond
form returns the value of condition.
If every condition evaluates to nil
, so that every clause fails, cond
returns nil
.
The following example has four clauses, which test for the cases where the value of x
is a number, string, buffer and symbol, respectively:
(cond ((numberp x) x) ((stringp x) x) ((bufferp x) (setq temporary-hack x) ; multiple body-forms (buffer-name x)) ; in one clause ((symbolp x) (symbol-value x)))
Often we want to execute the last clause whenever none of the previous clauses was successful. To do this, we use t
as the condition of the last clause, like this: (t body-forms)
. The form t
evaluates to t
, which is never nil
, so this clause never fails, provided the cond
gets to it at all. For example:
(setq a 5) (cond ((eq a 'hack) 'foo) (t "default")) ⇒ "default"
This cond
expression returns foo
if the value of a
is hack
, and returns the string "default"
otherwise.
Any conditional construct can be expressed with cond
or with if
. Therefore, the choice between them is a matter of style. For example:
(if a b c) ≡ (cond (a b) (t c))
It can be convenient to bind variables in conjunction with using a conditional. It’s often the case that you compute a value, and then want to do something with that value if it’s non-nil
. The straightforward way to do that is to just write, for instance:
(let ((result1 (do-computation))) (when result1 (let ((result2 (do-more result1))) (when result2 (do-something result2)))))
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:
(when-let* ((result1 (do-computation)) (result2 (do-more result1))) (do-something result2))
There’s a number of variations on this theme, and they’re briefly described below.
Evaluate each binding in varlist, stopping if a binding value is nil
. If all are non-nil
, return the value of then-form, otherwise the last form in else-forms.
Each element of varlist
has the form (symbol value-form)
: value-form is evaluated and symbol is locally bound to the result. Bindings are sequential, as in let*
(see Local Variables). As a special case, symbol can be omitted if only the test result of value-form is of interest: value-form is evaluated and checked for nil
, but its value is not bound.
Evaluate each binding in varlist, stopping if a binding value is nil
. If all are non-nil
, return the value of the last form in then-forms.
varlist has the same form as in if-let*
: Each element of varlist
has the form (symbol value-form)
, in which value-form is evaluated and symbol is locally bound to the result. Bindings are sequential, as in let*
(see Local Variables). As a special case, symbol can be omitted if only the test result of value-form is of interest: value-form is evaluated and checked for nil
, but its value is not bound.
Evaluate each binding in varlist, stopping if a binding value is nil
. If all are non-nil
, return the value of the last form in then-forms, or, if there are no then-forms, return the value of the last binding.
varlist has the same form as in if-let*
: Each element of varlist
has the form (symbol value-form)
, in which value-form is evaluated and symbol is locally bound to the result. Bindings are sequential, as in let*
(see Local Variables). As a special case, symbol can be omitted if only the test result of value-form is of interest: value-form is evaluated and checked for nil
, but its value is not bound.
Some Lisp programmers follow the convention that and
and and-let*
are for forms evaluated for return value, and when
and when-let*
are for forms evaluated for side-effect with returned values ignored.
A similar macro exists to run a loop until one binding evaluates to nil
:
Evaluate each binding in spec in turn, stopping if a binding value is nil
. If all are non-nil
, execute then-forms, then repeat the loop. Note that when the loop is repeated, the value-forms in spec are re-evaluated and the bindings are established anew.
varlist has the same form as in if-let*
: Each element of varlist
has the form (symbol value-form)
, in which value-form is evaluated and symbol is locally bound to the result. Bindings are sequential, as in let*
(see Local Variables). As a special case, symbol can be omitted if only the test result of value-form is of interest: value-form is evaluated and checked for nil
, but its value is not bound.
The return value of while-let
is always nil
.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4