我可以为循环指定自定义求和函数(例如vector-add
)吗?
我想做这样的事情:
(loop for vec in '((1 2) (3 4)) sum vec)
;=> (4 6)
答案 0 :(得分:4)
这是一个有趣的问题。如果你能做到这一点会很好,但简短的回答是“不”。根据HyperSpec的6.1.3 Value Accumulation Clauses:
sum
构造形成了连续主值的累积和 每次迭代时提供的表单参数 var 是 用来积累总和;如果提供了 var ,则loop不会返回 最后的总和自动。 var 参数的绑定就像是 将with
构造为适当类型的零。后续值 (包括任何必要的强制)计算就好像是通过函数 的+
即可。如果使用into
var ,则可以使用 type-spec 为 var 提供类型参数;如果是非数字,则后果未指定 提供类型。如果没有into
变量,则可选 type-spec 参数适用于保持总和的内部变量。该 默认类型是依赖于实现的;但它必须是超类型 类型 数字。
您的实际用例是否这么简单(循环遍历列表并计算它们的向量总和)还是更复杂?如果是这么简单,你可以用reduce
做你想做的事。它看起来更像是
(reduce 'vector-add '((1 2) (3 4)))
其中vector-add
是您的自定义求和函数。如果您仍需要使用loop
,则可以使用reduce
中的for sum = ... then ...
和明确的loop
获得finally (return sum)
类行为。首先,定义为vector-add
,
(defun vector-add (x y)
(mapcar '+ x y))
(vector-add '(1 2) '(3 4))
;=> (4 6)
我们可以做到:
(loop
for vec in '((1 2) (3 4) (5 6))
for sum = vec then (vector-add sum vec)
finally (return sum))
;=> (9 12)
答案 1 :(得分:3)
您可以使用iterate
库执行此操作:
(ql:quickload "iterate")
(use-package :iterate)
(defun vector-add (x y) (mapcar '+ x y))
(iter (for i in '((1 2) (3 4))) (reducing i by #'vector-add)) ; (4 6)
答案 2 :(得分:1)
除了使用带有for ... = ... then ...
子句的特殊求和函数之外,另一种自定义求和的方法是使用sum ... into ...
子句:
(loop for (n1 n2) in '((1 2) (3 4))
sum n1 into s1
sum n2 into s2
finally (return (list s1 s2)))