Loops Common Lisp-将函数应用于列表中的所有其他元素

Loops Common Lisp-将函数应用于列表中的所有其他元素,loops,lisp,common-lisp,Loops,Lisp,Common Lisp,我想将函数(*x 2)应用于列表中的每个其他元素,并使用循环宏返回整个列表。到目前为止,我提出的解决方案是: (defun double-every-other (xs) (loop for x in xs by #'cddr collect (* x 2))) 但是,这将使每个其他元素加倍,并且只返回加倍的元素,因此如果我执行: (double-every-other '(1 2 3 4)) 结果将是: '(4 8) 但我希望结果是: '(1 4 3 8) 有没有一种方法可以使用(

我想将函数(*x 2)应用于列表中的每个其他元素,并使用循环宏返回整个列表。到目前为止,我提出的解决方案是:

(defun double-every-other (xs)
  (loop for x in xs by #'cddr collect (* x 2)))
但是,这将使每个其他元素加倍,并且只返回加倍的元素,因此如果我执行:

(double-every-other '(1 2 3 4))
结果将是:

'(4 8)
但我希望结果是:

'(1 4 3 8)

有没有一种方法可以使用(循环)来实现这一点?

例如,您可以在扫描列表时测试一个递增的整数:

(defun double-every-other (xs)
  (loop for x in xs
     for i from 1
     if (oddp i)
     collect x
     else collect (* x 2)))

另一个版本的数学知识更少:

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

显然,您将无法像其他答案那样轻松地抽象出N(如果您想的是“宏”,请立即停止)。这里我们使用
on
关键字进行迭代,这意味着依次访问每个子列表。由于我们使用#的cddr的
,因此会跳过其他每个子列表。解构语法
(ab)
绑定已访问列表的第一个和第二个元素。

另一个版本,完全没有循环:

(defun double-every-other (xs)
  (loop for x in xs
        for doublep = nil then (not doublep)
        collect (if doublep (* x 2) x)))
(defun make-cycled (&rest items)
  (setf (cdr (last items)) items))

(mapcar #'funcall
        (make-cycled #'identity (lambda (x) (* 2 x)))
        '(10 9 8 7 6 5 4 3))

;;=> (10 18 8 14 6 10 4 6)

您可以使用
循环
“on”列表迭代原语。这将获取一个循环变量列表,这些变量将“涂抹”整个列表,最后一个变量是整个剩余列表的尾部。如果我们有奇数个参数,则有必要使用的条件
循环
,以避免将
nil
相乘

(defun double-every-other (list)
  (loop for (single double tail) on list by #'cddr
    if (null double)
      collect single
    else
      append (list single (* 2 double))))
如果我们尝试运行它:

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

(1 4 3 8 5)

对于元素数为奇数的列表不起作用。@Renzo谢谢,我错过了它