在Clojure中,可以通过函数for
的帮助迭代序列,或类似地使用doseq
进行副作用,并将nil作为返回值:
(doseq [x (range 3)]
(prn x))
; 0
; 1
; 2
对于序列无限的情况,有一种方法可以引入中断条件:
(doseq [x (range) :while (< x 3)]
(prn x))
这将产生与上面相同的输出。
作为一种专业,当您使用多个序列时,会有一个非常有趣的行为。正如文档所称:&#34;集合以嵌套方式迭代,最快最快&#34;。
(doseq [x (range 3) y (range 3)]
(prn x y))
; 0 0
; 0 1
; 0 2
; 1 0
; 1 1
; 1 2
; 2 0
; 2 1
; 2 2
但是,如果序列再次无限,会发生什么。当最后一个是无限的时,它运作得很好。这将像以前的例子一样起作用:
(doseq [x (range 3) y (range) :while (< y 3)]
(prn x y))
如果第一个是无限的,则结果输出符合预期,但由于某些原因,在打印完最后一行之后循环不会停止。换句话说:repl继续工作。
(doseq [x (range) y (range 3) :while (< x 3)]
(prn x y))
有人可以解释这种行为吗?
答案 0 :(得分:13)
这没有意义:
(doseq [x (range)
y (range 3)
:while (< x 3)]
(prn x y))
应该是:
(doseq [x (range)
:while (< x 3)
y (range 3)]
(prn x y))
...终止。
这样想:
(doseq [x (range)]
(doseq [y (range 3)
:while (< x 3)]
(prn x y)))
VS
(doseq [x (range)
:while (< x 3)]
(doseq [y (range 3)]
(prn x y)))
在原始版本中,外环是无限的,内环中的:while
没有区别。循环继续,它什么都不做。在固定版本中:while
终止外部循环。
答案 1 :(得分:0)
鉴于muhuk的优秀解释,对于明确而不是过度压缩代码似乎是一个很好的论据。所以也许这样:
(doseq [x (range 3)]
(doseq [y (range 3)]
(prn x y)))
如果你可以控制输入序列,或者像这样:
(let [x-vals (range)
y-vals (range) ]
(doseq [x x-vals :while (< x 3)]
(doseq [y y-vals :while (< y 3)]
(prn x y))))
如果来自呼叫者的输入序列(例如x-vals
或y-vals
)。