krokodil
krokodil

Reputation: 1366

Summing vectors with common lisp 'loop' macro

I need to implement something like this:

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

except that accumulated values are represent lists of numbers like (1 2 3) and they are added element-wise. In other words I would like to initialize summation with (zerov N) and use (v+) to add subsequent elements:

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

Is it possible to do something like this with loop macro? I can implement it as a separate function, but I would like to use loop or loop-like macro for expressiveness. Perhaps there is a way to define simple loop-like macro just for this case?

Upvotes: 2

Views: 1822

Answers (3)

huaiyuan
huaiyuan

Reputation: 26529

(reduce #'v+ (loop for i from 1 to n collect (f i))
        :initial-value (zerov n))

Note that Common Lisp has proper "vector" (i.e., sequence of elements of homogeneous type allowing more compact representation and efficient random access), so perhaps,

(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)))

Upvotes: 0

Barmar
Barmar

Reputation: 780909

(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))

Upvotes: 3

Rainer Joswig
Rainer Joswig

Reputation: 139261

LOOP as defined in the Common Lisp standard is not extensible.

I would write it with the normal LOOP functionality:

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

The I would write it as a function:

(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))

If you want such a functionality as a direct language feature of a loopy macro, then an alternative would be the ITERATE macro, which is more powerful than the LOOP macro and it is also extensible.

Upvotes: 2

Related Questions