ELisp: 如何在 'else' 块中执行多个表达式?

4

当使用ELisp时,我如何在if语句的else块中执行多个表达式?

2个回答

13

不需要使用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


5

菲尔的回答是正确和惯用的。如果你想在ifelse块中执行多个语句,并且只关心Emacs Lisp,请使用他的答案。

在Emacs Lisp和Common Lisp中,当你想要按顺序执行多个操作以进行副作用(例如更改变量、在屏幕上打印某些内容,通常与函数返回值无关的任何事情),然后只返回一个表达式的值时,你可以使用prognprog1prog2。它们都会评估其中的所有表单,但只分别返回最后一个、第一个和第二个表达式的值。

(progn 1 2 3 4 5) 返回 5,(prog1 1 2 3 4 5) 返回 1,(prog2 1 2 3 4 5) 返回 2。显然这些并没有什么用,因为在 prognprog1prog2 中评估表单的目的是为了副作用。因此以下所有内容都会在 echo area(以及 *Messages* 缓冲区)中打印字符串 αβγδ,但只有一个字符串将被返回:

(progn (message "α") (message "β") (message "γ") (message "δ")) ; => "δ"
(prog1 (message "α") (message "β") (message "γ") (message "δ")) ; => "α"
(prog2 (message "α") (message "β") (message "γ") (message "δ")) ; => "β"

所有三个函数都存在于Emacs Lisp和Common Lisp中。但是,如果您想返回第三个表达式的值怎么办?没有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 θ

在Emacs Lisp中,您仍然需要使用prognprog1prog2等来分组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”。

2
这不是最好的答案。使用 progn 是可以的,但更可读的方法是考虑到 else 中允许有多个表达式。事实上,elisp 程序员经常会围绕这个事实来有意识地组织整个结构(如果你有一个成功步骤有多个步骤的正向测试,则制作一个负向测试,其中这些步骤就是 else)。 - nic ferrier
取决于您想要返回什么。如果您想返回最后一个表达式的值,则可以使用phils的答案或这个答案。如果您想返回第一个表达式的值,则可以使用prog1。如果您想返回系列中任意表达式的值,请在progn中嵌套prog1。 - R. P. Dillon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接