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

Dea*_*hen 4 emacs elisp

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

phi*_*ils 10

您不需要progn这个,因为这已经是默认行为:

C-hf if RET

if是"C源代码"中的特殊形式.

(如果COND那么......)

如果COND产生非零,那么执行THEN,否则执行ELSE ...
返回THEN的值或最后一个ELSE的值.
那么必须是一个表达式,但ELSE ...可以是零个或多个表达式.
如果COND产生nil,并且没有ELSE,则值为nil.

重新使用sindikat的例子:

(if (> 1 2)
    (message "True")
  (message "False")
  (message "I repeat, completely false"))
Run Code Online (Sandbox Code Playgroud)

当然,progn如果您希望评估THEN表单中的多个表达式,您可以使用它.


Mir*_*lov 5

菲尔斯的回答是正确且惯用的。如果您想在else块中执行多个语句if,并且您只关心 Emacs Lisp,请遵循他的答案。

\n\n

在 Emacs Lisp 和 Common Lisp 中,当您想要按顺序执行多个操作以产生副作用时(例如更改变量、在屏幕上打印一些内容,通常是与函数返回值无关的任何内容),然后返回仅使用其中一种表达式,即prognprog1、 或prog2。它们都评估其中的所有形式,但分别只返回最后一个、第一个和第二个表达式的值。

\n\n

(progn 1 2 3 4 5)返回 5、(prog1 1 2 3 4 5)返回 1、返回 2。这显然是无用的,因为评估, ,内(prog2 1 2 3 4 5)的形式的目的是为了产生副作用。因此,以下所有内容都会在回显区域(和缓冲区)中打印 string , , , ,但只会返回字符串之一:prognprog1prog2\xce\xb1\xce\xb2\xce\xb3\xce\xb4*Messages*

\n\n
(progn (message "\xce\xb1") (message "\xce\xb2") (message "\xce\xb3") (message "\xce\xb4")) ; => "\xce\xb4"\n(prog1 (message "\xce\xb1") (message "\xce\xb2") (message "\xce\xb3") (message "\xce\xb4")) ; => "\xce\xb1"\n(prog2 (message "\xce\xb1") (message "\xce\xb2") (message "\xce\xb3") (message "\xce\xb4")) ; => "\xce\xb2"\n
Run Code Online (Sandbox Code Playgroud)\n\n

所有 3 个函数都存在于 Emacs Lisp 和 Common Lisp 中。但是如果您想返回第三个表达式的值怎么办?没有prog3。结合现有的!以下所有返回\xce\xb3

\n\n
(progn (message "\xce\xb1") (message "\xce\xb2") (prog1 (message "\xce\xb3") (message "\xce\xb4"))) ; => "\xce\xb3"\n(prog1 (progn (message "\xce\xb1") (message "\xce\xb2") (message "\xce\xb3")) (message "\xce\xb4")) ; => "\xce\xb3"\n(prog2 (message "\xce\xb1") (progn (message "\xce\xb2") (message "\xce\xb3")) (message "\xce\xb4")) ; => "\xce\xb3"\n(prog2 (message "\xce\xb1") (prog2 (message "\xce\xb2") (message "\xce\xb3") (message "\xce\xb4"))) ; => "\xce\xb3"\n
Run Code Online (Sandbox Code Playgroud)\n\n

在 Common Lisp 中,要将语句分组在一起并仅返回 中最后一个的值if,您可以这样做:

\n\n
(if t\n    (progn (message "\xce\xb5") (message "\xce\xb6"))\n    (progn (message "\xce\xb7") (message "\xce\xb8"))) ; returns \xce\xb6\n(if nil\n    (progn (message "\xce\xb5") (message "\xce\xb6"))\n    (progn (message "\xce\xb7") (message "\xce\xb8"))) ; returns \xce\xb8\n
Run Code Online (Sandbox Code Playgroud)\n\n

在 Emacs Lisp 中,您仍然必须将then块中的语句与progn, prog1,分组prog2,但您else不必这样做,因此 phils 的答案。在 Emacs Lisp 中(if nil 1 2 3)会返回 3,而在 Common Lisp 中会返回 3 too many parameters for special operator IF

\n\n

另请参阅:“ Emacs Lisp Intro ”中的“ 8.1.4 The \'progn\' Special Form ”部分。

\n

  • 这不是最好的答案。使用 progn 是可以的,但是与 else 中允许使用多个表达式这一事实相比,它更具可读性。事实上,elisp 程序员经常围绕这一事实故意组织整个构造(如果您有一个积极的测试,其中成功步骤是多个步骤,那么进行一个消极的测试,其中这些步骤是其他步骤)。 (2认同)