想了解为什么下面示例中的 SOME 函数返回不一致的结果

Would like to understand why the SOME function in examples below are returning inconsistent results

我是 common lisp 的新手,我在 linux 中使用 SBCL(版本 2.1.5), 我正在学习 SOME 应用运算符,我 运行 这两个 在我看来给出不一致结果的示例:

第一次调用对我来说有意义,但第二次调用 似乎不一致。为什么第二次调用也不会 return 'T' 喜欢第一次调用吗?

感谢您帮助理解这一点。

让我们看一个更简单的SOME例子:

(SOME #'EVENP '(1 2 3 4 5))

它更简单,因为只有一个值序列被迭代。 因此,预计谓词将被赋予一个参数。这里的结果是 T 因为输入列表中的某些元素满足 EVENP.

当您有多个序列时,它们会并行迭代:每个序列的第一个元素一起用作谓词的参数。 然后将所有第二个元素用作对谓词的第二次调用的参数,等等,直到至少一个序列为空。

例如,让我们定义一个接受两个参数的函数divisible-by

USER> (defun divisible-by (value divisor)
        (= 0 (mod value divisor)))
DIVISIBLE-BY

你可以说,例如 (DIVISIBLE-BY 10 5) 它会 return T.

我们也 TRACE 它(实际跟踪输出取决于实现,这里我使用的是 SBCL)。

USER> (trace divisible-by)
(DIVISIBLE-BY)

让我们在调用 SOME 时使用它,有 2 个列表(任何其他数量的序列都是错误的):

USER> (some #'divisible-by '(10 20 30) '(3 7 6))
  0: (DIVISIBLE-BY 10 3)
  0: DIVISIBLE-BY returned NIL
  0: (DIVISIBLE-BY 20 7)
  0: DIVISIBLE-BY returned NIL
  0: (DIVISIBLE-BY 30 6)
  0: DIVISIBLE-BY returned T
T

您可以看到,两个列表中的每对元素都用作对 divisible-by.

的连续调用的参数

同样的逻辑适用于 Common Lisp 中的其他 higher-order 函数:

USER> (mapcar #'list '(0 1 2) '(a b c) '(x y z))
((0 A X) (1 B Y) (2 C Z))
(some #'= '(1 2 3 4) '(4 3 2 1))

表示

(or (= 1 4)
    (= 2 3)
    (= 3 2)
    (= 4 1))

即:函数 = 应用于给定序列的第一个元素,然后应用于第二个元素,依此类推。一旦其中一个序列用完,它就会结束。

如果你想在两个列表之间设置交集(:test在这里有点多余,因为默认测试eql也比较数字):

(intersection '(1 2 3 4) '(4 3 2 1) :test #'=)

这returns整个路口。如果只需要检测是否有共同成员,找到就结束,可以这样:

(find-if (lambda (e)
           (member e '(4 3 2 1)))
         '(1 2 3 4))

(loop :for e :in '(1 2 3 4)
      :thereis (member e '(4 3 2 1)))