Skip to content

LISP - 逻辑谓词

在 Common Lisp 中,逻辑操作对于控制 if、cond、when 和 unless 等构造中的程序流程至关重要。Lisp 的真值处理方式既简单又强大。

与许多具有明确 true 和 false 布尔值的语言不同,Lisp 拥有一套**广义布尔值(generalized boolean)**系统:

  • nil:符号 nil 表示假值。它是唯一且仅有的假值。
  • 其他一切皆为真:在布尔上下文中,任何非 nil 的值都被视为真。这包括符号 t、数字(如 0 和 1)、字符串、列表以及所有其他对象。

符号 t 是规范的或默认的真值,但任何非 nil 的值同样有效。

Lisp 中主要的逻辑运算符是 and、or 和 not。

运算符描述
and从左到右评估其参数。一旦遇到 nil 参数,它会立即停止并返回 nil。如果所有参数都为真,它将返回最后一个参数的值。
or从左到右评估其参数。它会立即停止并返回找到的第一个非 nil 参数的值。如果所有参数都为 nil,则返回 nil。
not接受一个参数。如果参数为 nil,则返回 t。如果参数为除 nil 之外的任何值,则返回 nil。函数 null 是 not 的同义词。

请注意,如果所有条件都为真,and 会返回最后一个表达式的值。

(write (and t t)) ; 都为真,返回最后一个值 -> T
(terpri)
(write (and t "hello" 1)) ; 都为真,返回最后一个值 -> 1
(terpri)
(write (and t nil 1)) ; 遇到 nil,短路 -> NIL
T
1
NIL

请注意,or 如何返回它找到的第一个真值。

(write (or nil nil)) ; 都为假 -> NIL
(terpri)
(write (or nil t 1)) ; 找到 t,短路 -> T
(terpri)
(write (or nil "hello" 1)) ; 找到 "hello",短路 -> "hello"
NIL
"hello"
T

not 只是简单地反转任何广义布尔值。

(write (not t)) ; 真值变为 nil -> NIL
(terpri)
(write (not 123)) ; 真值变为 nil -> NIL
(terpri)
(write (not nil)) ; 唯一的假值变为 t -> T
(terpri)
(write (null nil)) ; `null` 是 `not` 的同义词 -> T
NIL
NIL
T
T

and 和 or 的短路行为通常被习惯性地用于简洁的条件逻辑。

(defun describe-item (item)
(and item (format t "Item is: ~a~%" item)))
(describe-item "A book") ; -> 打印 "Item is: A book"
(describe-item nil) ; -> 不做任何事并返回 NIL