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