3.8 If–then–else 表达式

if 表达式可以带有一个可选的第三个参数,称为 否则部分(else-part),用于真假判断返回假的情况。 当判断为假时,整个 if 表达式的第二个参数(即那么部分) 不会 被求值,而第三个参数(否则部分) 被求值。 你可以把它理解为阴天版的决策:“如果天气温暖晴朗,就去海边, 否则就在家看书!”。

Lisp 代码中并不会写出单词“else”;if 表达式的否则部分 直接写在那么部分之后。在 Lisp 代码书写中,否则部分通常 单独起一行,缩进比那么部分更少:

(if true-or-false-test
    action-to-carry-out-if-the-test-returns-true
  action-to-carry-out-if-the-test-returns-false)

例如,下面的 if 表达式按常规方式求值时, 会打印消息 ‘4 is not greater than 5!’:

(if (> 4 5)                               ; if-part
    (message "4 falsely greater than 5!") ; then-part
  (message "4 is not greater than 5!"))   ; else-part

可以看到,不同层级的缩进让那么部分和否则部分很容易区分。 (GNU Emacs 提供了多个命令,可以自动为 if 表达式正确缩进。 See GNU Emacs Helps You Type Lists。)

我们可以扩展 type-of-animal 函数, 只需在 if 表达式中增加一个部分,即可加入否则分支。

你可以对下面这个版本的 type-of-animal 函数定义求值以安装它, 然后对后续两个表达式求值,传入不同参数,就能看到效果。

(defun type-of-animal (characteristic)  ; Second version.
  "Print message in echo area depending on CHARACTERISTIC.
If the CHARACTERISTIC is the string \"fierce\",
then warn of a tiger; else say it is not fierce."
  (if (equal characteristic "fierce")
      (message "It is a tiger!")
    (message "It is not fierce!")))

(type-of-animal "fierce")

(type-of-animal "striped")

(type-of-animal "fierce") 求值时,回显区会打印: "It is a tiger!";而对 (type-of-animal "striped") 求值时,会打印 "It is not fierce!"

(当然,如果 characteristic"ferocious", 同样会打印 "It is not fierce!",这就会产生误导! 编写代码时,需要考虑到 if 可能会测试到这类参数, 并相应地设计程序。)