if
替代 or
的 insert-buffer
要完成的任务是确保 buffer
的值是一个缓冲区本身,而不是缓冲区的名称。如果值是名称,则必须获取缓冲区本身。
你可以想象自己在一个会议上,一个引座员正拿着一张带有你的名字的名单四处寻找你:引座员与你的名字绑定,而不是与你绑定;但当引座员找到你并搀扶你的手臂时,引座员就与你绑定了。
在 Lisp 中,你可以这样描述这种情况:
(if (not (holding-on-to-guest)) (find-and-take-arm-of-guest))
我们想要使用缓冲区做同样的事情——如果我们没有缓冲区本身,我们就希望获取它。
使用一个叫做 bufferp
的谓词,它告诉我们是否有一个缓冲区(而不是它的名称),我们可以这样编写代码:
(if (not (bufferp buffer)) ; if-部分 (setq buffer (get-buffer buffer))) ; then-部分
这里,if
表达式的真假测试是 (not (bufferp buffer))
;然后部分是表达式 (setq buffer (get-buffer buffer))
。
在测试中,函数 bufferp
如果其参数是一个缓冲区,则返回 true——但如果其参数是缓冲区的名称,则返回 false。 (函数名 bufferp
的最后一个字符是字符 ‘p’;正如我们前面看到的,‘p’ 的这种用法是一个约定,表示该函数是一个谓词,这是一个术语,表示该函数将确定某个属性是真还是假。See 使用错误类型的对象作为参数.)
函数 not
位于表达式 (bufferp buffer)
之前,因此真假测试看起来像这样:
(not (bufferp buffer))
not
是一个函数,如果其参数为 false,则返回 true;如果其参数为 true,则返回 false。因此,如果 (bufferp buffer)
返回 true,则 not
表达式返回 false,反之亦然。
使用这个测试,if
表达式的工作方式如下:当变量 buffer
的值实际上是一个缓冲区而不是其名称时,真假测试返回 false,if
表达式不会评估 then-部分。这是可以的,因为如果它确实是一个缓冲区,我们就不需要对变量 buffer
做任何操作。
另一方面,当 buffer
的值不是一个缓冲区本身,而是缓冲区的名称时,真假测试返回 true,并且评估表达式的 then-部分。在这种情况下,then-部分是 (setq buffer (get-buffer buffer))
。该表达式使用 get-buffer
函数通过名称返回实际的缓冲区本身。然后,setq
将变量 buffer
设置为缓冲区本身的值,替换其先前的值(该值是缓冲区的名称)。