for

added
1.0

ns
clojure.core

type
macro

(for seq-exprs body-expr)

List comprehension. Takes a vector of one or more
binding-form/collection-expr pairs, each followed by zero or more
modifiers, and yields a lazy sequence of evaluations of expr.
Collections are iterated in a nested fashion, rightmost fastest,
and nested coll-exprs can refer to bindings created in prior
binding-forms.  Supported modifiers are: :let [binding-form expr ...],
:while test, :when test.

(take 100 (for [x (range 100000000) y (range 1000000) :while (< y x)] [x y]))

                ;; prepare a seq of the even values 
;; from the first six multiples of three
(for [x [0 1 2 3 4 5]
      :let [y (* x 3)]
      :when (even? y)]
  y)
;;=> (0 6 12)

            
                (def digits (seq [1 2 3]))
(for [x1 digits x2 digits] (* x1 x2))
;;=> (1 2 3 2 4 6 3 6 9)
            
                ;; produce a seq of all pairs drawn from two vectors
(for [x ['a 'b 'c] 
      y [1 2 3]]
  [x y])
;;=> ([a 1] [a 2] [a 3] [b 1] [b 2] [b 3] [c 1] [c 2] [c 3])

(for [suburb ['("name" location)
              '("name2" location2)
              '("name3" location3)]
      pollutant ["CO2" "SO2"]]
  (conj (into [] (flatten [suburb pollutant])) (rand-int 10)))
;;=> (["name" location "CO2" 9]   ["name" location "SO2" 2] 
;;    ["name2" location2 "CO2" 2] ["name2" location2 "SO2" 0] 
;;    ["name3" location3 "CO2" 7] ["name3" location3 "SO2" 0])
            
                ;; produce a seq of the first three powers for a range of integers
(for [x (range 1 6) 
      :let [y (* x x) 
            z (* x x x)]] 
  [x y z])
;;=> ([1 1 1] [2 4 8] [3 9 27] [4 16 64] [5 25 125])

            
                ;; produce a seq of squares
(for [x (range 3 7)] 
  (* x x))
;;=> (9 16 25 36)
            
                ;; prepare a seq of all keys from entries whose values are 0
(for [[x y] '([:a 1] [:b 2] [:c 0]) :when (= y 0)] x)
;;=> (:c)

            
                ;; Demonstrating performance difference between :when and :while

(time (dorun (for [x (range 1000) y (range 10000) :when (> x y)] [x y])))
;; "Elapsed time: 2898.908 msecs"
;;=> nil

(time (dorun (for [x (range 1000) y (range 10000) :while (> x y)] [x y])))
;; "Elapsed time: 293.677 msecs"
;;=> nil

            
                ;; Demonstrating functional difference between :when and :while

(for [x (range 3) y (range 3)] [x y])
;;=> ([0 0] [0 1] [0 2] 
;;    [1 0] [1 1] [1 2]
;;    [2 0] [2 1] [2 2])

(for [x (range 3) y (range 3) :when (not= x y)] [x y])
;;=> (      [0 1] [0 2] 
;;    [1 0]       [1 2] 
;;    [2 0] [2 1]      )

; Here we see the :while applied to the immediately preceding seq
(for [x (range 3) y (range 3) :while (not= x y)] [x y])
;;=> (             
;;    [1 0]              
;;    [2 0] [2 1]      )

;; The placement of the :while is important
;; :while can cause a halt for a particular sequence

(for [x (range 3) y (range 3) :while (not= x 1)] [x y])
;;=> ([0 0] [0 1] [0 2] [2 0] [2 1] [2 2])

(for [x (range 3) :while (not= x 1) y (range 3)] [x y])
;;=> ([0 0] [0 1] [0 2])

            
                ;; More examples illustrating the difference between :when and :while

;; Simple but inefficient method of checking whether a number is
;; prime.
user=> (defn prime? [n]
         (not-any? zero? (map #(rem n %) (range 2 n))))
#'user/prime?

user=> (range 3 33 2)
(3 5 7 9 11 13 15 17 19 21 23 25 27 29 31)

;; :when continues through the collection even if some have the
;; condition evaluate to false, like filter
user=> (for [x (range 3 33 2) :when (prime? x)]
         x)
(3 5 7 11 13 17 19 23 29 31)

;; :while stops at the first collection element that evaluates to
;; false, like take-while
user=> (for [x (range 3 33 2) :while (prime? x)]
         x)
(3 5 7)

;; The examples above can easily be rewritten with filter or
;; take-while.  When you have a for with multiple binding forms, so
;; that the iteration occurs in a nested fashion, it becomes possible
;; to write something briefly with 'for' that would be more verbose or
;; unwieldy with nested filter or take-while expressions.

user=> (for [x (range 3 17 2) :when (prime? x)
             y (range 3 17 2) :when (prime? y)]
         [x y])
([ 3 3] [ 3 5] [ 3 7] [ 3 11] [ 3 13]
 [ 5 3] [ 5 5] [ 5 7] [ 5 11] [ 5 13]
 [ 7 3] [ 7 5] [ 7 7] [ 7 11] [ 7 13]
 [11 3] [11 5] [11 7] [11 11] [11 13]
 [13 3] [13 5] [13 7] [13 11] [13 13])

user=> (for [x (range 3 17 2) :while (prime? x)
             y (range 3 17 2) :while (prime? y)]
         [x y])
([3 3] [3 5] [3 7]
 [5 3] [5 5] [5 7]
 [7 3] [7 5] [7 7])

;; This example only gives a finite result because of the :while
;; expressions.
user=> (for [x (range) :while (< x 10) 
             y (range) :while (<= y x)]
         [x y])

([0 0]
 [1 0] [1 1]
 [2 0] [2 1] [2 2]
 [3 0] [3 1] [3 2] [3 3]
 [4 0] [4 1] [4 2] [4 3] [4 4]
 [5 0] [5 1] [5 2] [5 3] [5 4] [5 5]
 [6 0] [6 1] [6 2] [6 3] [6 4] [6 5] [6 6]
 [7 0] [7 1] [7 2] [7 3] [7 4] [7 5] [7 6] [7 7]
 [8 0] [8 1] [8 2] [8 3] [8 4] [8 5] [8 6] [8 7] [8 8]
 [9 0] [9 1] [9 2] [9 3] [9 4] [9 5] [9 6] [9 7] [9 8] [9 9])

            
                ;; Here are a couple of examples where the only difference is where
;; the :while is placed, but it makes a significant difference in the
;; behavior.

;; When x=2 y=1 is reached, :while (<= x y) evaluates false, so all
;; further items in the y collection are skipped.  When x=3 y=1 is
;; reached, the same thing happens.

user=> (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]
 [1 2 1] [1 2 2] [1 2 3]
 [1 3 1] [1 3 2] [1 3 3])

;; This is different.  When x=2 y=1 z=1 is reached, :while (<= x y)
;; evaluates false, but since the :while is after the binding for z,
;; all further items in the z collection are skipped.  Then x=2 y=2
;; z=1 is tried, where the while expresssion evaluates true.

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

            
                (defn all-files-present?
"Takes a list of real file names, and returns a map of files present 1
and not present 0."
[file-seq]
(for [fnam file-seq
 :let [stat-map {(keyword fnam) (look-for fnam "f")}]]
  stat-map))

(into {}  (all-files-present? '("Makefile" "build.sh" "real-estate.csv")))

{:Makefile 1, :build.sh 1, :real-estate.csv 0}
            
                ;; Flattening a seq of pairs using for comprehensions

(def pairs (for [i (range 10)] [i (inc i)]))
;; ([0 1] [1 2] [2 3] [3 4] [4 5] [5 6] [6 7] [7 8] [8 9] [9 10])

(def flattened (for [pair pairs element pair] element))
;; (0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10)
            
                ;; Given an array of integers, return indices of the two numbers such that they 
;; add up to a specific target.

;; You may assume that each input would have exactly one solution.
;; Given nums = [2, 7, 11, 15], target = 9,

;; Because nums[0] + nums[1] = 2 + 7 = 9,
;; return [0, 1].

(defn two-sum [nums target]
  (let [nums-index (zipmap nums (range))
        indexs (for [[x i] nums-index
                     [y j] nums-index
                     :when (< i j)
                     :when (= (+ x y) target)]
                 [i j])]
    (first indexs)))

(two-sum [2 7 11 15] 9)
;; [0 1]

            
                ;;; Cartesian products of two sets

(#(set
   (for[x %1, y %2]
     [x y])) #{1 2 3} #{4 5})

;=> #{[2 5] [3 4] [1 4] [1 5] [2 4] [3 5]}
            
                ;; Nested 'for' example to produce indexes of Two-dimensional array
(for [i (range 3)]
   (for [j (range 3)]
      [i j]))

;=> (([0 0] [0 1] [0 2]) 
;    ([1 0] [1 1] [1 2]) 
;    ([2 0] [2 1] [2 2]))