当使用ELisp时,我如何在if
语句的else
块中执行多个表达式?
不需要使用progn
,因为这已经是默认行为:
C-hf if
RET
if
是C源代码中的特殊形式。(if COND THEN ELSE...)
如果COND为真,则执行THEN,否则执行ELSE...
返回THEN或最后一个ELSE的值。
THEN必须是一个表达式,但ELSE...可以是零个或多个表达式。
如果COND为nil,并且没有ELSE,则返回nil。
以sindikat的示例为例:
(if (> 1 2)
(message "True")
(message "False")
(message "I repeat, completely false"))
如果你希望在THEN
表达式中评估多个表达式,当然可以使用progn
。
菲尔的回答是正确和惯用的。如果你想在if
的else
块中执行多个语句,并且只关心Emacs Lisp,请使用他的答案。
在Emacs Lisp和Common Lisp中,当你想要按顺序执行多个操作以进行副作用(例如更改变量、在屏幕上打印某些内容,通常与函数返回值无关的任何事情),然后只返回一个表达式的值时,你可以使用progn
、prog1
或prog2
。它们都会评估其中的所有表单,但只分别返回最后一个、第一个和第二个表达式的值。
(progn 1 2 3 4 5)
返回 5,(prog1 1 2 3 4 5)
返回 1,(prog2 1 2 3 4 5)
返回 2。显然这些并没有什么用,因为在 progn
、prog1
、prog2
中评估表单的目的是为了副作用。因此以下所有内容都会在 echo area(以及 *Messages*
缓冲区)中打印字符串 α
、β
、γ
、δ
,但只有一个字符串将被返回:
(progn (message "α") (message "β") (message "γ") (message "δ")) ; => "δ"
(prog1 (message "α") (message "β") (message "γ") (message "δ")) ; => "α"
(prog2 (message "α") (message "β") (message "γ") (message "δ")) ; => "β"
prog3
。结合已有的函数!以下所有内容都将返回γ
:(progn (message "α") (message "β") (prog1 (message "γ") (message "δ"))) ; => "γ"
(prog1 (progn (message "α") (message "β") (message "γ")) (message "δ")) ; => "γ"
(prog2 (message "α") (progn (message "β") (message "γ")) (message "δ")) ; => "γ"
(prog2 (message "α") (prog2 (message "β") (message "γ") (message "δ"))) ; => "γ"
在Common Lisp中,要将语句分组并仅返回 if
中最后一个语句的值,可以这样做:
(if t
(progn (message "ε") (message "ζ"))
(progn (message "η") (message "θ"))) ; returns ζ
(if nil
(progn (message "ε") (message "ζ"))
(progn (message "η") (message "θ"))) ; returns θ
progn
、prog1
、prog2
等来分组then
块中的语句,但在else
块中则不需要,这就是phils的答案。在Emacs Lisp中,(if nil 1 2 3)
将返回3,而在Common Lisp中,它会出现错误提示too many parameters for special operator IF
。 另请参阅:“8.1.4 The 'progn' Special Form”一节,摘自“Emacs Lisp Intro”。