Common lisp 公共口齿不清:what';在列表中循环遍历连续对的最佳方式是什么?

Common lisp 公共口齿不清:what';在列表中循环遍历连续对的最佳方式是什么?,common-lisp,Common Lisp,有时,我需要在列表中的连续对之间循环。我现在的做法是 (loop for x on lst while (not (null (cdr x))) (do something on (car x) and (cadr x))) 我想知道是否有更好的/内置的方法来做到这一点 我之所以需要它,是因为有时我需要,例如,一些添加连续对的函数 (1 2 3 4 5) ----> (3 5 7 9) 有没有像reduce这样的内置函数可以让我实现这个功能?好吧,没有一个内置函数可以实现

有时,我需要在列表中的连续对之间循环。我现在的做法是

(loop for x on lst while (not (null (cdr x)))
       (do something on (car x) and (cadr x)))
我想知道是否有更好的/内置的方法来做到这一点

我之所以需要它,是因为有时我需要,例如,一些添加连续对的函数

(1 2 3 4 5) ----> (3 5 7 9)

有没有像reduce这样的内置函数可以让我实现这个功能?

好吧,没有一个内置函数可以实现你想要的功能。你可以试着用
maplist
组合一些东西,但我的第一反应是也要使用
loop

不过,只需写几条注释就可以了。首先,
(not(null foo))
相当于CL中的
foo
,因为非
NIL
值通过布尔运算被视为
t
。其次,
loop
可以解构它的参数,这意味着您可以像

(loop for (a b) on lst while b
      collect (+ a b))
maplist
版本看起来像

(maplist 
   (lambda (rest) 
     (when (cdr rest) 
        (+ (first rest) (second rest)))
   lst)

我认为不那么可读(这也会返回NIL作为结果的最后一个元素,而不是仅仅在它结束之前)。

< P>我相信保罗·格雷厄姆在OnLisp有一个名为Multuple元组的函数。它可以按cdr、cddr或您喜欢的方式在列表中下移。这里是它的一个评论版本。它使用他的回指if宏aif

(defun map-tuple (someList f &optional (by #'cdr))
 "(map-tuple someList f &optional (by #'cdr))
   f is a function that takes two args, returns one val (maybe)
   the map-tuple will collect all non-nil results in a list.
    example: 
(map-tuple '(1 2 3 4 5 6) (lambda (a b) (format T \"a: ~A b:~A~%\" a b)) #'cdr) 
a: 1 b:2
a: 2 b:3
a: 3 b:4
a: 4 b:5
a: 5 b:6
a: 6 b:NIL

(map-tuple '(1 2 3 4 5 6) (lambda (a b) (format T \"a: ~A b:~A~%\" a b)) #'cddr) 
a: 1 b:2
a: 3 b:4
a: 5 b:6
"
  (cond ((null someList)
        nil)
    (T
       (aif (funcall f (car someList) (cadr someList))
          (cons it (map-tuple (funcall by someList) f by))
           (map-tuple (funcall by someList) f by)))))

为什么我要在这件事上投反对票?这是一个错误的问题吗?不是我的否决票,但可能是因为你的伪代码没有运行,但看起来很像真实的CL,有人被愚弄了?谢谢,我喜欢你建议的优雅方式。还有,是否可以优雅地枚举所有对或无序对?现在我正在做
?(setf s’(12345))?(成员x s)collect(列表x y)中的x循环(成员x s)collect(列表x y)中的y循环)(11)(12)(13)(14)(15)(22)(23)(24)(25)(33)(34)(35)(35)(4)(4)(4)(5))
这种操作通常会更优雅地处理。在这种特定情况下,我将定义类似于
(defun pair with(elem list)(mapcar(lambda(a)(list elem a))list))
,然后调用
(mapcon(lambda(rest)(pair with(car rest))s)
。获取所有对看起来非常相似。因此在(ab)@claytontstanley中有一个隐式的“&rest some arg not used”-我认为它比这更复杂,因为您可以在…上执行
(a.rest)循环或
(a b)循环((12)(3 4)…
。但就本例而言,是的,这基本上是正确的。依赖于将尾部递归优化为循环是一个坏主意。标准明确规定,不保证这样做,事实上,除非启用优化,否则SBCL甚至不会这样做。循环解决方案要好得多。