LISP - `every` 函数
Lisp - every 函数
Section titled “Lisp - every 函数”every 函数是 Common Lisp 中一个强大的高阶函数(higher-order function),用于测试给定**谓词(predicate)**是否对一个或多个序列的每个元素都为真。它是进行数据验证和属性测试的简洁而富有表现力的工具。
(every predicate sequence &rest more-sequences)- predicate(谓词):一个函数(或函数名符号),它接受与所提供序列数量相同的参数。它应该在为真时返回非
nil值,在为假时返回nil。 - sequence(序列):第一个要测试的序列(列表、向量或字符串)。
- more-sequences(更多序列):可选的额外序列。
如果谓词对所有元素都为真,则返回 T。如果谓词对任何元素返回 nil,every 会立即停止处理并返回 nil。
示例 1:基本谓词检查
Section titled “示例 1:基本谓词检查”让我们测试序列中的所有数字是否都是偶数。
main.lisp
Section titled “main.lisp”;; 在列表上使用内置谓词 'evenp'(print (every #'evenp '(2 4 6 8 10))); => T
;; 在向量上使用 'evenp'(print (every #'evenp #(2 4 6 8 10))); => T
;; 包含奇数的失败示例(print (every #'evenp '(2 4 5 6 8))); => NILTTNIL示例 2:使用自定义 lambda 谓词
Section titled “示例 2:使用自定义 lambda 谓词”您可以利用 lambda 函数即时定义一个自定义测试。
main.lisp
Section titled “main.lisp”;; 检查所有数字是否大于 0(正数)(let ((numbers '(1 5 12 99))) (print (every #'(lambda (x) (> x 0)) numbers))); => T
;; 检查所有字符串的长度是否为 3(let ((words '("cat" "dog" "ant"))) (print (every #'(lambda (word) (= (length word) 3)) words))); => T
;; 失败示例(let ((mixed-words '("cat" "fish" "ant"))) (print (every #'(lambda (word) (= (length word) 3)) mixed-words))); => NILTTNIL示例 3:处理多个序列
Section titled “示例 3:处理多个序列”当您提供多个序列时,谓词在每一步会从每个序列中接收一个元素。迭代在最短的序列耗尽时停止。
main.lisp
Section titled “main.lisp”;; 检查两个列表中对应元素是否相等(print (every #'= '(1 2 3) '(1 2 3))); => T
;; 相等性检查的失败示例(print (every #'= '(1 2 3) '(1 5 3))); => NIL
;; 检查第一个列表中的每个元素是否小于第二个列表中对应的元素(print (every #'< '(10 20 30) '(11 22 33))); => TTNILT实际应用与最佳实践
Section titled “实际应用与最佳实践”- 数据验证:确保数据集中的所有项都符合特定格式或约束,例如
(every #'valid-email-p user-emails)。 - 状态检查:在游戏或模拟中,检查所有对象是否共享特定状态,例如
(every #'is-enemy-defeated? active-enemies)。 - 算法前置条件:在运行复杂算法之前,验证输入数据是否满足要求。
- 专家提示:
every函数有“兄弟姐妹”!使用some来检查谓词是否对至少一个元素为真,使用notany来检查谓词是否对所有元素都为假,使用notevery来检查谓词是否对至少一个元素为假。 - 调试技巧:如果
every意外返回nil,您可以通过将谓词包装在一个lambda中来调试,该lambda会打印它正在测试的值,例如(every #'(lambda (x) (format t "Testing: ~a~%" x) (evenp x)) my-list)。