在Common Lisp循环中定义局部变量

Noo*_*oob 3 variables loops common-lisp

我想知道是否有一种方法可以在Common Lisp loop构造中引入一些局部变量,而无需对其进行任何自动增量-就像说可以避免在循环外使用let的快捷语法一样。

Syl*_*ter 10

我们将从简单开始。如果让循环对任何累加单词执行某些操作,则只需命名绑定即可创建绑定。在这里,我进行两个绑定oddsevens由于我希望返回两个值,并且计数是“黑带循环”中所述的动词之一,当然还有CLHS循环规范

(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
Run Code Online (Sandbox Code Playgroud)

在文档中也描述了更通用的方式是使用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
Run Code Online (Sandbox Code Playgroud)

您已经知道了,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
Run Code Online (Sandbox Code Playgroud)

最后一个例子&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))
Run Code Online (Sandbox Code Playgroud)

请注意,我们不需要使用tat,finally因为更改的绑定可以在外部使用loop

知道CL可能比我想念的还要多,但这是我使用的那些。