How can I execute more than one expression in the else
block of an if
statement, when using ELisp?
You don't need progn
for this, as this is already the default behaviour:
C-hf if
RET
if is a special form in `C source code'.
(if COND THEN ELSE...)
If COND yields non-nil, do THEN, else do ELSE...
Returns the value of THEN or the value of the last of the ELSE's.
THEN must be one expression, but ELSE... can be zero or more expressions.
If COND yields nil, and there are no ELSE's, the value is nil.
To re-use sindikat's example:
(if (> 1 2)
(message "True")
(message "False")
(message "I repeat, completely false"))
You would, of course, use progn
if you wished to evaluate multiple expressions in the THEN
form.
phils's answer is correct and idiomatic. If you want to execute several statements in the else
block of if
, and you're concerned only with Emacs Lisp, go with his answer.
In Emacs Lisp and Common Lisp when you want to perform multiple actions in sequence for side effects (like change a variable, print something on screen, generally, anything that has nothing to do with function returning a value), and then return the value of only one of the expressions, you use progn
, prog1
, or prog2
. They all evaluate all the forms inside them, but return only the value of last, first and second expression respectively.
(progn 1 2 3 4 5)
returns 5, (prog1 1 2 3 4 5)
returns 1, (prog2 1 2 3 4 5)
returns 2. This is clearly useless, because the point of evaluating forms inside progn
, prog1
, prog2
is for side effects. So all of the following would print string α
, β
, γ
, δ
in echo area (and in *Messages*
buffer), but only one of the strings will be returned:
(progn (message "α") (message "β") (message "γ") (message "δ")) ; => "δ"
(prog1 (message "α") (message "β") (message "γ") (message "δ")) ; => "α"
(prog2 (message "α") (message "β") (message "γ") (message "δ")) ; => "β"
All 3 functions exist both in Emacs Lisp and Common Lisp. But what if you want to return the 3rd expression's value? There is no prog3
. Combine existing ones! All of the following return γ
:
(progn (message "α") (message "β") (prog1 (message "γ") (message "δ"))) ; => "γ"
(prog1 (progn (message "α") (message "β") (message "γ")) (message "δ")) ; => "γ"
(prog2 (message "α") (progn (message "β") (message "γ")) (message "δ")) ; => "γ"
(prog2 (message "α") (prog2 (message "β") (message "γ") (message "δ"))) ; => "γ"
In Common Lisp to group statements together and return only the last one's value in if
, you would do:
(if t
(progn (message "ε") (message "ζ"))
(progn (message "η") (message "θ"))) ; returns ζ
(if nil
(progn (message "ε") (message "ζ"))
(progn (message "η") (message "θ"))) ; returns θ
In Emacs Lisp you still have to group statement in then
block with progn
, prog1
, prog2
, but you in else
block you don't have to, thus phils's answer. In Emacs Lisp (if nil 1 2 3)
would return 3, while in Common Lisp it would err with too many parameters for special operator IF
.
See also: Section "8.1.4 The 'progn' Special Form" from "Emacs Lisp Intro".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With