我想知道是否有一种方法可以在Common Lisp loop
构造中引入一些局部变量,而无需对其进行任何自动递增-就像避免使用let的快捷语法一样在循环之外。
答案 0 :(得分:10)
我们将从简单开始。如果让循环对任何累加单词执行某些操作,则只需命名绑定即可创建绑定。在这里,我进行了两个绑定odds
和evens
,因为我希望返回两个值,而counting是Loop for black belts中所描述的动词之一,当然还有CLHS loop specification中所描述的动词之一:
(loop :for num :in '(1 3 5 6 3 3)
:counting (oddp num) :into odds
:counting (evenp num) :into evens
:finally (return (values odds evens)))
; ==> 5
; ==> 1
在文档中也描述了更通用的方式是使用with
子句:
(loop :with odds := 0 :and evens := 0
:for num in '(1 3 5 6 3 3)
:if (oddp num) :do (incf odds)
:else :do (incf evens)
:finally (return (values odds evens)))
; ==> 5
; ==> 1
您已经知道for e = value then new-value
了,因为它可以逐步执行,但是我将其添加到此处以供完成。请注意,顺序很重要:
(loop :for odds := 0 :then (if (oddp num) (1+ odds) odds)
:for evens := 0 :then (if (evenp num) (1+ evens) evens)
:for num :in '(1 3 5 6 3 3)
:finally (return (values odds evens)))
; ==> 5
; ==> 1
最后一个例子是函数中有&aux
个元素。它创建let*
绑定而没有let*
和缩进。通常,这是一个真正的选择:
(defun count-odds (list &aux (odds 0) (evens 0))
(loop :for num in list
:if (oddp num) :do (incf odds)
:else :do (incf evens))
(values odds evens))
请注意,我们不需要使用finally
,因为更改后的绑定在loop
之外可用
知道CL可能比我想念的还要多,但这是我使用的那些。