使用doseq/for无限序列

Ant*_*ald 6 clojure clojurescript

在Clojure中,可以通过函数的帮助迭代序列,for或类似地使用doseq副作用并将nil作为返回值:

(doseq [x (range 3)]
    (prn x))

; 0
; 1
; 2
Run Code Online (Sandbox Code Playgroud)

对于序列无限的情况,有一种方法可以引入中断条件:

(doseq [x (range) :while (< x 3)]
    (prn x))
Run Code Online (Sandbox Code Playgroud)

这将产生与上面相同的输出.

作为专业,当您使用多个序列时,会有一个非常有趣的行为.正如文档所称:"集合以嵌套方式迭代,最快速".

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

但是,如果序列再次无限,会发生什么.当最后一个是无限的时,它运作得很好.这将像以前的例子一样工作:

(doseq [x (range 3) y (range) :while (< y 3)]
    (prn x y))
Run Code Online (Sandbox Code Playgroud)

如果第一个是无限的,则结果输出符合预期,但由于某些原因,循环在最后一行打印后不会停止.换句话说:repl继续工作.

(doseq [x (range) y (range 3) :while (< x 3)]
    (prn x y))
Run Code Online (Sandbox Code Playgroud)

任何人都可以解释这种行为吗?

muh*_*huk 13

这没有意义:

(doseq [x (range) 
        y (range 3) 
        :while (< x 3)]
  (prn x y))
Run Code Online (Sandbox Code Playgroud)

它应该是:

(doseq [x (range) 
        :while (< x 3)
        y (range 3)]
  (prn x y))
Run Code Online (Sandbox Code Playgroud)

...终止.

想一想:

(doseq [x (range)]
  (doseq [y (range 3) 
          :while (< x 3)]
    (prn x y)))
Run Code Online (Sandbox Code Playgroud)

VS:

(doseq [x (range)
        :while (< x 3)]
  (doseq [y (range 3)]
    (prn x y)))
Run Code Online (Sandbox Code Playgroud)

在原始版本中,外部循环是无限的,:while在内部循环中没有区别.循环继续,它什么都不做.在固定版本中:while终止外部循环.