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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With