Sunday, July 19, 2015

4Clojure: For the Win

(for [x (range 40)
    :when (= 1 (rem x 4))]
    x)

x is assigned the range of integer values from 0-39. x is finite so the for stops evaluating when x is fully consumed.
On each iteration the remainder of x/4 is compared to 1 and if they are equal the body is evaluated (which is just x).

(for [x (iterate #(+ 4 %) 0)
    :let [z (inc x)]
    :while (< z 40)]
    z)

x is assigned a lazy sequence of all the multiples of 4 (iterate from 0 applying +4 at each step using an anonymous function). x is infinite so the for is terminated with :while
Each iteration of the for symbol z is assigned x+1.
While z is less than 40 the body is evaluated (which is just z) and the for loop terminates when z >= 40.

(for [[x y] (partition 2 (range 20))]
    (+ x y))

The range from 0-20 is split into segments of 2 numbers. One segment deconstructed into x and y per iteration of the for. The sequence is finite so the for terminates when the full sequence is consumed.
x and y are added as the body of the for.

Each of these results in the same output (a list of each multiple of 4 incremented by 1 up to 37) just by a different mechanism. For my money the first option is probably the best combination of concise and obvious.

Clojure for macro keywords

These docs weren't incredibly helpful in figuring out the difference between :when and :while.
The examples
(for [x [1 2 3]
  y [1 2 3]
  :while (<= x y)
  z [1 2 3]]
  [x y z])
and

(for [x [1 2 3]
  y [1 2 3]
  z [1 2 3]
  :while (<= x y)]
  [x y z])

come close to exposing the difference, but what should really be stated explicitly somewhere is that :while stops attempting to evaluate at the first false result whereas (almost said while there >.> ) :when continues to try to evaluate after the false.

(for [x [1 2 3]
  y [1 2 3]
  :while (= x y)
  z [1 2 3]]
  [x y z])
;;([1 1 1] [1 1 2] [1 1 3])
(for [x [1 2 3]
  y [1 2 3]
  :when (= x y)
  z [1 2 3]]
  [x y z])
;;([1 1 1] [1 1 2] [1 1 3] [2 2 1] [2 2 2] [2 2 3] [3 3 1] [3 3 2] [3 3 3])

Perhaps I'm dense but this wasn't immediately obvious to me.

Edit: Or perhaps I should have actually read. Example 8 is pretty explicit. >.<