Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using the for list comprehension returns unexpected results

so I try this code

(for [x (range 1 8) y (range 1 8) :while (and (< x y) (even? x))] [x y])

and get back ()

but I try this:

(for [x (range 1 8) y (range 1 8) :while (and (< y x) (even? x))] [x y])

and I get the desired result. What effect did changing the positions of x and y have? The first snippet shouldn't return an empty list.. after all there have to be some even x's smaller than y

like image 893
Jeroko Avatar asked Feb 14 '23 07:02

Jeroko


1 Answers

In Clojure, (for [x (range 1 8) y (range 1 8)] [x y]) returns the cartesian product of x and y with y running from 1 to 7 for each and every iteration of x.

From the 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])

In your examples, :while is associated with y and not x. So the :while applies for every iteration of y and then restarts after the next iteration of x.

To make this clearer, note that you can also associate :while with x:

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])

which runs the loop while x is odd, then breaks.

So in your first example, :while breaks on every single iteration on y when y equals 1 because there is no value of x for which (and (< x 1) (even? x)) holds true.

Your second example, on the other hand, works because even though :while breaks on the first iteration of y because (< 1 1) yields false, the second iteration of y succeeds because x starts from 2, so if y is 1, and (and (< y x) (even? x)) is (and (< 1 2) (even? 2)) which evaluates to true.

See http://clojuredocs.org/clojure_core/clojure.core/for for more details. Especially the part showing the difference between :when and :while.

like image 183
DJG Avatar answered May 02 '23 09:05

DJG