LISP - 比较谓词
Lisp - 比较与相等性谓词
Section titled “Lisp - 比较与相等性谓词”在 Lisp 中,谓词是一种测试条件并返回布尔值的函数。与许多其他语言不同,Lisp 的规范布尔值是 t 符号表示真,nil 符号表示假。这些谓词是控制 if、cond、when 和 unless 等程序流程结构的基础。
本教程涵盖两类主要的谓词:用于数值比较的谓词和用于检查任意 Lisp 对象之间相等性的谓词。
数值比较谓词
Section titled “数值比较谓词”这些函数用于比较数值。Common Lisp 的一个强大特性是它们可以接受两个以上的参数并顺序执行比较。
| 谓词 | 描述 |
|---|---|
< | 如果数字按单调递增顺序排列,则返回 t。例如,(< 1 3 5) 为 t。 |
> | 如果数字按单调递减顺序排列,则返回 t。例如,(> 5 3 1) 为 t。 |
<= | 如果数字按单调非递减顺序排列,则返回 t。例如,(<= 3 3 5) 为 t。 |
>= | 如果数字按单调非递增顺序排列,则返回 t。例如,(>= 5 5 3) 为 t。 |
= | 如果所有数值参数的值都相等,则返回 t。例如,(= 5 5.0) 为 t。 |
/= | 如果没有两个数值参数的值相等,则返回 t。例如,(/= 1 2 3) 为 t。 |
示例:数值谓词
Section titled “示例:数值谓词”让我们在 SBCL (Steel Bank Common Lisp) 这样的现代 Common Lisp 环境中看看这些函数的实际应用。
;; main.lisp
;; 基础的两个参数比较(print (< 3 5)) ; T(print (> 3 5)) ; NIL
;; 多个参数比较(print (< 10 20 30)) ; T(print (>= 50 25 25 1)) ; T
;; 数字的相等性检查(print (= 10 10 10)) ; T(print (= 10 10.0)) ; T (类型不同,但值相同)
;; 不等性检查(print (/= 5 3 5)) ; NIL (因为第一个和第三个相等)(print (/= 5 4 3)) ; TTNILTTTTNILT通用相等性谓词
Section titled “通用相等性谓词”选择正确的相等性谓词是 Lisp 中的常见任务,对正确性至关重要。它们在比较对象的严格程度上有所不同。
| 谓词 | 描述与用例 |
|---|---|
eq | 同一性:如果参数是内存中的同一个对象,则返回 t。速度非常快。用于比较符号或检查两个变量是否指向完全相同的对象。 |
eql | 非数字的同一性,数字的值相等性:类似于 eq,但如果参数是相同类型和值的数字,也返回 t。这是 case 的默认谓词。 |
equal | 结构相等性:递归比较列表、字符串和其他结构的内容。如果它们具有相似的结构和等效的内容,则返回 t。速度较慢,但对于结构化数据更直观。 |
equalp | 宽松相等性:类似于 equal,但更宽松。它忽略字符串/字符中的大小写和数字类型差异(例如,(equalp 5 5.0) 为 t)。 |
示例:选择正确的相等性谓词
Section titled “示例:选择正确的相等性谓词”;; main.lisp
(let ((list-a (list 'x 'y)) (list-b (list 'x 'y)))
;; EQ 检查内存中的同一个对象 (print (eq 'hello 'hello)) ; T (符号是唯一的) (print (eq list-a list-b)) ; NIL (它们是两个不同的列表对象) (print (eq list-a list-a)) ; T (是同一个对象)
(terpri) ; 换行以提高可读性
;; EQL 类似于 EQ,但适用于相同类型的数字 (print (eql 10 10)) ; T (print (eql 10 10.0)) ; NIL (不同类型)
(terpri)
;; EQUAL 检查结构相似性 (print (equal "hello" "hello")) ; T (print (equal list-a list-b)) ; T (内容是等效的)
(terpri)
;; EQUALP 更宽松 (print (equalp "hello" "Hello")) ; T (不区分大小写) (print (equalp 10 10.0)) ; T (忽略数字类型))TNILT
TNIL
TT
TT最佳实践与深入学习
Section titled “最佳实践与深入学习”- 默认使用
eql: 当不确定时,从eql开始。它是一个安全高效的默认选择。 - 对数字使用
=: 总是使用=进行数值相等性比较,因为它能正确处理不同的数字类型(例如,整数与浮点数)。 - 对列表和字符串使用
equal: 当你需要比较数据结构的内容时,equal是你的工具。 - 避免对数字和列表使用
eq: 对数字或新创建的列表使用eq可能会导致意想不到的行为,因为编译器不被要求重用相同的内存对象。 - 延伸阅读: 如需深入了解,请查阅 Common Lisp Hyperspec,它是该语言的官方标准。