使用for list comprehension会返回意外结果

Jer*_*oko 4 list-comprehension clojure

所以我试试这个代码

(for [x (range 1 8) y (range 1 8) :while (and (< x y) (even? x))] [x y])
Run Code Online (Sandbox Code Playgroud)

并回来()

但我试试这个:

(for [x (range 1 8) y (range 1 8) :while (and (< y x) (even? x))] [x y])
Run Code Online (Sandbox Code Playgroud)

我得到了理想的结果.改变x和y的位置有什么影响?第一个片段不应该返回一个空列表..毕竟必须有一些小于y的偶数x

DJG*_*DJG 8

在Clojure中,(for [x (range 1 8) y (range 1 8)] [x y])返回的笛卡尔乘积xyy运行17每个和每次迭代x.

从repl:

user=> (for [x (range 1 8) y (range 1 8)] [x y])
([1 1] [1 2] [1 3] [1 4] [1 5] [1 6] [1 7] [2 1] [2 2] [2 3] [2 4] [2 5] [2 6] [2 7] [3 1] [3 2] [3 3] [3 4] [3 5] [3 6] [3 7] [4 1] [4 2] [4 3] [4 4] [4 5] [4 6] [4 7] [5 1] [5 2] [5 3] [5 4] [5 5] [5 6] [5 7] [6 1] [6 2] [6 3] [6 4] [6 5] [6 6] [6 7] [7 1] [7 2] [7 3] [7 4] [7 5] [7 6] [7 7])
Run Code Online (Sandbox Code Playgroud)

在你的例子,:while与关联y,而不是x.因此:while适用于每次迭代,y然后在下一次迭代后重新启动x.

为了使这更清楚,请注意,您还可以关联:whilex:

user=> (for [x (range 1 8) :while (odd? x) y (range 1 8)] [x y])
([1 1] [1 2] [1 3] [1 4] [1 5] [1 6] [1 7])
Run Code Online (Sandbox Code Playgroud)

x奇数时运行循环,然后中断.

因此,在你的第一个例子中,:while打破了在每一次迭代上y时,y等于1因为没有价值x为其(and (< x 1) (even? x))持有true.

另一方面,你的第二个例子是有效的,因为即使:while在第一次迭代中y因为(< 1 1)yield 而中断false,第二次迭代y成功因为x2,所以如果y1,并且(and (< y x) (even? x))(and (< 1 2) (even? 2))哪个求值true.

有关详细信息,请参阅http://clojuredocs.org/clojure_core/clojure.core/for.尤其是部分示出之间的差:when:while.