Common Lisp内置了一个强大的Loop宏。它非常实用且功能强大,而且我经常使用它。
我也听说过一个非常类似的东西,名为Iterate。它看起来与Loop非常相似,但它有更多的Lispy感觉。这两者有什么不同?除了简单的风格偏好外,是否有任何理由可以改用其中任何一种?
答案 0 :(得分:0)
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 提供收集、nconcing 和附加功能。 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
那样的并行绑定,而是 not needed?。
我可能在这里失踪了。
但这还不是全部,还有更多不同之处。