LISP - 谓词链
Lisp - 现代谓词逻辑
Section titled “Lisp - 现代谓词逻辑”在 Lisp 中,谓词 (predicate) 是一个测试条件并返回广义布尔值(T (真) 或 NIL (假))的函数。链式谓词允许你从简单、可重用的测试构建复杂的逻辑。这是函数式编程中的一项核心技术,可生成清晰且可维护的代码。
逻辑运算符:and、or、not
Section titled “逻辑运算符:and、or、not”结合谓词的主要工具是逻辑运算符,它们具有短路求值 (short-circuiting evaluation) 的特性:
and:从左到右评估形式。一旦有任何形式返回NIL,则立即停止并返回NIL。如果所有形式都评估为真,则返回最后一个形式的值。or:从左到右评估形式。遇到第一个非NIL值时立即停止并返回该值。如果所有形式都评估为NIL,则返回NIL。not:接受一个参数。如果参数为NIL,则返回T;如果参数不是NIL,则返回NIL。
示例:定义一个复杂谓词
Section titled “示例:定义一个复杂谓词”与编写一次性检查不同,将复杂逻辑封装在专门的谓词函数中是一种最佳实践。让我们创建一个函数来检查一个数字是否是正偶数。
main.lisp
Section titled “main.lisp”(defun positive-even-p (x) "Predicate that returns T if X is a positive and even integer, otherwise NIL." (and (integerp x) ;; 是整数吗? (plusp x) ;; 是正数吗?(比 (> x 0) 更地道) (evenp x))) ;; 是偶数吗?
;; --- 测试用例 ---(format t "Is 10 a positive even number? ~a~%" (if (positive-even-p 10) 'Yes 'No))(format t "Is 11 a positive even number? ~a~%" (if (positive-even-p 11) 'Yes 'No))(format t "Is -4 a positive even number? ~a~%" (if (positive-even-p -4) 'Yes 'No))(format t "Is 'hello a positive even number? ~a~%" (if (positive-even-p 'hello) 'Yes 'No))执行代码将产生以下清晰的输出:
Is 10 a positive even number? YesIs 11 a positive even number? NoIs -4 a positive even number? NoIs 'hello a positive even number? No序列谓词的高阶函数
Section titled “序列谓词的高阶函数”Lisp 提供了强大的高阶函数,可将谓词应用于序列(如列表或向量)。这是函数式风格的基石。
every:如果谓词对于序列中的每个元素都为真,则返回T。some:如果谓词对于至少一个元素为真,则返回第一个非NIL的结果。notany:如果谓词对于所有元素都为假,则返回T。notevery:如果谓词对于至少一个元素为假,则返回T。
实用示例:验证数据集
Section titled “实用示例:验证数据集”假设你有一个传感器读数列表,并且你想验证所有读数都是在可接受范围内的有效数字。
main.lisp
Section titled “main.lisp”(defun valid-reading-p (reading) "Predicate to check if a sensor reading is a number between 0 and 100." (and (numberp reading) (>= reading 0) (<= reading 100)))
(let ((dataset-a '(78 92 100 65)) (dataset-b '(88 95 101 70)) ;; 包含一个超出范围的值 (dataset-c '(66 'error 93))) ;; 包含一个非数值
(format t "Is dataset A valid? ~a~%" (if (every #'valid-reading-p dataset-a) 'Yes 'No)) (format t "Is dataset B valid? ~a~%" (if (every #'valid-reading-p dataset-b) 'Yes 'No)) (format t "Is dataset C valid? ~a~%" (if (every #'valid-reading-p dataset-c) 'Yes 'No)))这演示了一个实用且可读的验证检查:
Is dataset A valid? YesIs dataset B valid? NoIs dataset C valid? No