Common Lisp 中是否有非延迟评估的 "and" 或 "or" 操作?

Are there non-lazily evaluated "and" or "or" operations in Common Lisp?

Common Lisp 中常用的 andor 运算符将延迟计算它们的操作数,例如and 会在遇到第一个 nil 时停止。我正在寻找一个不以这种方式工作的运算符,而是总是在返回结果之前评估所有操作数。有这样的吗?

例如,在 C 中,您有惰性 && 和按位 &,它们可以用作非惰性替代方案。 我知道 logandbit-and,但它们不适用于布尔操作数。

例如:

(and NIL (not-defined))

不会抛出错误,但我希望它抛出一个错误。

(defun and* (&rest l)
  (every #'identity l))

如果全部为真则返回最后一个值

(defun and& (&rest l)
  (or (null l)
      (loop for b in l
            unless b
              do (return nil)
            finally (return b))))

(defun and& (&rest l)
  (or (null l)
      (loop for b in l
            always b
            finally (return b))))

一个可能的实现是

(defun and* (&rest x)
  (let ((res T))
    (dolist (item x)
      (if (null item) (return-from and* item))
      (setf res item))
    res))

解释:

  • 我们将结果初始化为T(这是需要的,因为(and)T
  • 我们遍历参数
  • 如果参数是 NIL 那么我们 return 它
  • 否则我们将项目存储为结果
  • 如果我们到达循环的末尾,那么我们 return 最后一项

or* 的实现更简单,因为 Common Lisp 中唯一的 "falsy" 值是 NIL 所以不需要记住最后一个 falsy 元素是什么,你可以使用some...

(defun or* (&rest x)
  (some #'identity x))

and* 的替代实现:

(defun and* (&rest values &aux (res t))
  (every (lambda (v) (setf res v)) values)
  res)

这 returns 最后一个非零值或 nil