5.2.4 函数体中的 or

insert-buffer 函数中 or 表达式的作用,是确保参数 buffer 绑定到缓冲区对象本身,而不只是缓冲区名称。上一节已经展示了如何用 if 表达式完成这一工作,但 insert-buffer 实际使用的是 or。要理解这一点,必须先了解 or 的工作方式。

or 函数可以接受任意数量的参数。它会依次对每个参数求值,并返回第一个不为 nil 的参数的值。此外,or 还有一个关键特性:在返回第一个非 nil 值之后,不会再对后续任何参数求值。

or 表达式如下:

(or (bufferp buffer)
    (setq buffer (get-buffer buffer)))

or 的第一个参数是表达式 (bufferp buffer)。如果 buffer 确实是缓冲区对象而非名称,该表达式会返回真(非 nil 值)。在 or 表达式中,如果出现这种情况,它会直接返回该真值,不再执行下一个表达式——这正是我们想要的,因为如果 buffer 已经是缓冲区对象,就无需再做任何处理。

反之,如果 (bufferp buffer) 的值为 nil(即 buffer 是缓冲区名称),Lisp 解释器就会执行 or 表达式的下一个元素,也就是 (setq buffer (get-buffer buffer))。该表达式会返回一个非 nil 值,也就是它为变量 buffer 设置的新值——这个值是缓冲区对象本身,而非名称。

这一切的最终结果是:符号 buffer 始终绑定到缓冲区对象,而非缓冲区名称。之所以必须这样做,是因为下一行的 set-buffer 函数只能操作缓冲区对象,不能直接使用缓冲区名称。

顺便一提,用 or 来描述之前引导员的例子,写法如下:

(or (holding-on-to-guest) (find-and-take-arm-of-guest))