Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Common Lisp - apply function to every other element in list

I want to apply the function (* x 2) to every other element in a list and return the entire list using the loop macro. The solution I've come up with so far is this:

(defun double-every-other (xs)
  (loop for x in xs by #'cddr collect (* x 2)))

However, this will double every other element and only return the elements that were doubled, so if I executed:

(double-every-other '(1 2 3 4))

The result would be:

'(4 8)

But I want the result to be:

'(1 4 3 8)

Is there a way I can do this using (loop)?

like image 234
lanour Avatar asked Nov 29 '22 23:11

lanour


1 Answers

Another version with less math:

(defun double-every-other (list)
  (loop
     for (a b) on list by #'cddr
     collect a
     when b collect (* b 2)))

(double-every-other '(1 2 3 4))
=> (1 4 3 8)

(double-every-other '(1 2 3 4 5))
=> (1 4 3 8 5)

Obviously, you won't be able to abstract the N as easily as the other answer (if you are thinking "macro", stop now). Here we iterate using the on keyword, which means each sublist is visited in turn. Since we use by #'cddr, every other sublist is skipped. The destructuring syntax (a b) binds the first and second elements of the visited list.

like image 158
coredump Avatar answered Dec 05 '22 00:12

coredump