2

我需要实现这样的事情:

(loop for i from 1 to N sum (f i))

除了累积值表示像 (1 2 3) 这样的数字列表并且它们是按元素添加的。换句话说,我想用 (zerov N) 初始化求和并使用 (v+) 添加后续元素:

(defun v+ (a b) (mapcar '+ a b))
(defun zerov (n) (loop for i from 1 to n collect 0))

可以用循环宏做这样的事情吗?我可以将它实现为一个单独的函数,但我想使用循环或类似循环的宏来表达。也许有一种方法可以为这种情况定义简单的类似循环的宏?

4

3 回答 3

3
(loop with accum = (make-list n :initial-element 0)
      for i from 1 to n
    do (setq accum (v+ accum (f i)))
  finally (return accum))
于 2013-01-25T23:37:19.770 回答
2

LOOPCommon Lisp 标准中定义的那样是不可扩展的。

我会用普通的 LOOP 功能编写它:

(let ((result (zerov n)))
  (loop for i from 1 to N
        do (setf result (v+ result (f i))))
  result)

我会把它写成一个函数:

(defun sum (n f init sum)
  (let ((result (funcall init n)))
    (loop for i from 1 to n
          do (setf result (funcall sum result (funcall f i))))
    result))

如果你想要一个像循环宏的直接语言特性这样的功能,那么一个替代方案是ITERATE宏,它比 LOOP 宏更强大,而且它也是可扩展的。

于 2013-01-25T23:37:45.183 回答
0
(reduce #'v+ (loop for i from 1 to n collect (f i))
        :initial-value (zerov n))

请注意,Common Lisp 具有适当的“向量”(即同质类型的元素序列,允许更紧凑的表示和有效的随机访问),所以也许,

(defun v+ (a b) (map-into a #'+ a b))
(defun zerov (n) (make-array n :initial-element 0))
(defun fn (i n) (let ((v (zerov n))) (setf (aref v i) 1) v))
(defun gn (n)
  (loop for v = (zerov n) then (v+ v (fn i n)) for i below n
        finally (return v)))
于 2013-01-26T08:43:25.277 回答