if 替代 or 的 insert-buffer ¶我们要完成的任务是确保 buffer 的值是缓冲区对象,而非缓冲区名称。如果值是名称,则必须获取对应的缓冲区对象。
你可以想象在一场会议中,引导员拿着写有你名字的名单四处找你:引导员一开始绑定的是你的名字,而非你本人;但当他找到你并牵起你的手,就绑定到了你本身。
在 Lisp 中,你可以这样描述这一场景:
(if (not (holding-on-to-guest))
(find-and-take-arm-of-guest))
我们对缓冲区要做的事情类似——如果没有拿到缓冲区对象,就去获取它。
使用判断是否为缓冲区的谓词函数 bufferp(而非名称),可以写出如下代码:
(if (not (bufferp buffer)) ; if-part (setq buffer (get-buffer buffer))) ; then-part
这里 if 表达式的真假判断是 (not (bufferp buffer));then 部分是表达式 (setq buffer (get-buffer buffer))。
在判断条件中,bufferp 函数在参数为缓冲区时返回真,为缓冲区名称时返回假。(函数名 bufferp 的最后一个字符是 ‘p’;如前所述,使用 ‘p’ 是一种惯例,表示该函数是谓词,即用于判断某一属性是否成立。参见 See Using the Wrong Type Object as an Argument。)
函数 not 位于表达式 (bufferp buffer) 之前,因此真假判断如下:
(not (bufferp buffer))
not 函数在参数为假时返回真,参数为真时返回假。因此如果 (bufferp buffer) 返回真,not 表达式返回假,反之亦然。
使用这一判断条件,if 表达式的工作逻辑如下:当变量 buffer 本身就是缓冲区对象而非名称时,真假判断返回假,if 表达式不会执行 then 部分。这符合预期,因为此时 buffer 已经是缓冲区,无需额外处理。
反之,当 buffer 的值不是缓冲区对象而是名称时,真假判断返回真,then 部分会被执行。此时 then 部分 (setq buffer (get-buffer buffer)) 会通过 get-buffer 函数根据名称获取真实缓冲区对象,再通过 setq 将变量 buffer 设置为该缓冲区对象,替换掉原先的名称值。