为什么这个 reduce 函数调用在 Common Lisp 中不起作用?

Why this reduce function call does not work in Common Lisp?

使用 Common Lisp (SBCL),我可以在 REPL 中成功求值:

CL-USER> (reduce #'+ '(1 2 3 4))
10

然而,这失败了:

> (reduce #'(lambda (e) (+ e 100))  '(1 2 3 4))

调试器抛出错误:

invalid number of arguments: 2

我期待的是累积效应,所以总和是 110

怎样才能达到预期的效果?我需要使用 reduce 以外的其他东西吗?

reducing 函数必须接受两个参数。您的 lambda 函数只接受一个。即使它有效,它也会将 100 添加到列表中每一步添加的结果中。

你的意思是指定初始值。最简单的 hacky 方法就是将它添加到您的列表中,例如

> (reduce #'+ (cons 100 '(1 2 3 4)))
110

正确的方法,the specs, is to explicitly specify it with the :initial-value keyword parameter:

> (reduce #'+ '(1 2 3 4) :initial-value 100)
110

如果您确实想在每个缩减步骤中添加 100

> (reduce #'(lambda (a x) (+ 100 a x)) '(1 2 3 4))
310

您可能还想再添加一个 100,方法是指定为 :initial-value

调用 (reduce #'f '(1 2 3 4)) 将计算

(f (f (f 1 2) 3) 4)

例如

>>> (reduce #'(lambda (a b) (cons a b)) '(1 2 3 4))
(((1 . 2) . 3) . 4)

因此,您传递给 reduce 的函数需要接受两个参数。首先使用序列的前两个元素调用此函数。然后使用上一次调用的结果和序列中的下一个元素等调用该函数(参见 [CLHS reduce])。要获得所有元素的总和,您需要调用以下命令:

>>> (reduce #'(lambda (a b) (+ a b)) '(1 2 3 4))
10

reduce 的行为可以通过提供初始值来改变。打电话

(reduce #'f '(1 2 3 4) :initial-value 100)

将计算以下内容:

(f (f (f (f 100 1) 2) 3) 4)

因此,如果您想获得想要的结果,您可以使用:

>>> (reduce #'+ '(1 2 3 4) :initial-value 100)
110

要将每个数字加 100 然后计算总和,可以使用 reducemapcar 的组合,这是函数式编程中的常见模式:

>>> (reduce #'+ (mapcar #'(lambda (a) (+ a 100)) '(1 2 3 4)))
410