Reputation: 1366
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
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
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
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