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

发布于 2025-01-16 12:11:03 字数 290 浏览 2 评论 0原文

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

  • (some #'= '(1 2 3 4 5) '(5 4 3 2 1))

  • (一些 #'= '(1 2 3 4) '(4 3 2 1)) 无

第一次调用对我来说有意义,但第二次调用 似乎不一致。为什么第二次调用不也 像第一次调用一样返回“T”?

感谢您帮助理解这一点。

I'm new to common lisp, and I am using SBCL (version 2.1.5) in linux,
I am learning about the SOME applicative operator, and I ran these 2
examples that seem to me to be giving inconsistent results:

  • (some #'= '(1 2 3 4 5) '(5 4 3 2 1))
    T

  • (some #'= '(1 2 3 4) '(4 3 2 1))
    NIL

The first invocation makes sense to me, but the second invocation
seems to be inconsistent. Why wouldn't the second invocation also
return 'T' like the first invocation?

Thanks for any help understanding this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

垂暮老矣 2025-01-23 12:11:03
(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 #'=)

这会返回整个交集。如果你只需要测试是否有共同成员,一找到就结束,你可以这样做:

(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)))
(some #'= '(1 2 3 4) '(4 3 2 1))

means

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

That is: the function = is applied to the first elements of the given sequences, then to the second elements and so on. It finishes as soon as one of the sequences is exhausted.

If you want to have the set intersection between two lists (the :test is a bit redundant here, because the default test eql also compares numbers):

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

This returns the entire intersection. If you only need to test whether there is any common member, finishing as soon as one is found, you could do it like this:

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

or

(loop :for e :in '(1 2 3 4)
      :thereis (member e '(4 3 2 1)))
池木 2025-01-23 12:11:03

让我们看一个更简单的 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) 并且它将返回

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

您可以看到两个列表中的每对元素都用作连续调用的参数可被除

同样的逻辑也适用于 Common Lisp 中的其他高阶函数:

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

Let's look at a simpler SOME example:

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

It is simpler because there is only one sequence of values being iterated.
As a consequence, the predicate is expected to be given a single argument. The result here is T because some elements in the input lists satisfy EVENP.

When you have more than one sequence, they are iterated in parallel: the first elements of each sequence are used together as arguments to the predicate.
Then all the second elements are used as arguments to the second call to the predicate, etc. until at least one sequence is empty.

For example, let's define a function divisible-by that takes two arguments:

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

You could say, for example (DIVISIBLE-BY 10 5) and it would return T.

Let's also TRACE it (the actual trace output is implementation dependent, here I'm using SBCL).

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

Let's use it in a call to SOME, with 2 lists (any other amount of sequences is an error):

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

You can see that each pair of elements from both lists are used as arguments to the successive calls to divisible-by.

The same logic applies to other higher-order functions in Common Lisp:

USER> (mapcar #'list '(0 1 2) '(a b c) '(x y z))
((0 A X) (1 B Y) (2 C Z))
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文