Common Lisp 中的 LOOP 和 Iterate 有什么区别?

问题描述 投票:0回答:2

Common Lisp 内置了一个强大的 Loop 宏。它非常有用且强大,我经常使用它。

我也听说过一个非常相似的东西,叫做“Iterate”。它看起来与 Loop 非常相似,但更有 Lispy 的感觉。这两者有什么区别?除了简单的风格偏好之外,是否还有任何理由切换到其中任何一个?

loops common-lisp
2个回答
2
投票
iterate

独有的一些东西:

条款没有严格的顺序

loop

要求所有

for
子句出现在循环体之前,例如在
while
之前。没关系
iter
:
(iter (for x in '(1 2 99)
  (while (< x 10))
  (for y = (print x))
  (collect (list x y)))

累积子句可以嵌套

collect

appending
等可以出现在任何地方:
(iter (for x in '(1 2 3))
  (case x
    (1 (collect :a))
    (2 (collect :b))))

finding

;; Finding the longest list in a list of lists:
(iter (for lst in '((a) (b c d) (e f)))
      (finding lst maximizing (length lst)))
=> (B C D)

;; The rough equivalent in LOOP:
(loop with max-lst = nil
      with max-key = 0
      for lst in '((a) (b c d) (e f))
      for key = (length lst)
      do
      (when (> key max-key)
        (setf max-lst lst
              max-key key))
      finally (return max-lst))
=> (B C D)

https://common-lisp.net/project/iterate/

第一个示例 找到区间内

x^2 - 4x + 1

的最小值:

(iter (for x from -5 to 5 by 1/100)
      (finding x minimizing (1+ (* x (- x 4)))))
2

©Common Lisp 食谱第 198 页

next-iteration

就像“继续”,而循环没有它。

iter

还有

first-iteration-p
(if-first-time then else)

https://web.archive.org/web/20170713081006/https://items.sjbach.com/211/comparing-loop-and-iterate

发电机

generate

next
。生成器是惰性的,当明确表示时它会转到下一个值。
(iter (for i in '(1 2 3 4 5))
      (generate c in-string "black")
      (if (oddp i) (next c))
      (format t "~a " c))
b b l l a 
NIL

https://sites.google.com/site/sabraonthehill/loop-v-iter

previous

(iter (for el in '(a b c d e))
      (for prev-el previous el)
      (collect (list el prev-el)))
=> ((A NIL) (B A) (C B) (D C) (E D))

尽管可以使用 
loop

的并行绑定

and
:
(loop for el in '(a b c d e)
      and prev-el = nil then el  
      collect (list el prev-el))

更多条款

in-string


LOOP 提供收集、查找和附加功能。 ITERATE 有这些,还有
adjoining

unioning
nunioning
accumulating

(iter (for el in '(a b c a d b)) (adjoining el)) => (A B C D)
adjoin

是集合运算)

LOOP有求和、计数、最大化、最小化。 ITERATE 还包括 

multiplying

reducing
。减少是广义减少构建器:
(iter (with dividend = 100)
      (for divisor in '(10 5 2))
      (reducing divisor by #'/ initial-value dividend))
=> 1

https://web.archive.org/web/20170713105315/https://items.sjbach.com/280/extending-the-iterate-macro

可扩展

(defmacro dividing-by (num &keys (initial-value 0)) `(reducing ,num by #'/ initial-value ,initial-value)) (iter (for i in '(10 5 2)) (dividing-by i :initial-value 100)) => 1

但还有更多。

https://common-lisp.net/project/iterate/doc/Rolling-Your-Own.html#Rolling-Your-Own

https://web.archive.org/web/20170713105315/https://items.sjbach.com/280/extending-the-iterate-macro

在附录中,我们看到两个loop扩展示例。但它们实际上并不可移植,代码充满了

#+(or allegro clisp-aloop cmu openmcl sbcl scl) (ansi-loop::add-loop-path …
sb-loop::add-loop-path
迭代中缺少的东西

没有像循环那样的并行绑定

and

,但是

不需要?
. 我可能失踪了。

但这还不是全部,还有更多差异。


0
投票

带有

finding

loop
示例让
loop
看起来太糟糕了。我通常会做某事:
(let ((longest))
  (loop for l in '((a) (b c d) (e f))
        do (when (> (length l) (length longest))
                 (setf longest l))
        finally (return longest)))
;; => (B C D)

do

子句中,您通常可以编写非常正常的 Common Lisp。 当某些变量在循环期间收集/记忆某些结果值时,用

let
setf
包装网络循环这些值非常有用。
但我明白,

generators

是一个杀手级功能。

    

© www.soinside.com 2019 - 2024. All rights reserved.