{:check ["true"], :ranks ["for" "for_advanced"]}
(require '[clojure.pprint :refer [pprint]])
(for ...)
¶;
; (for ...) evaluates to a sequence
;
(for [i (range 10)]
(str "i=" i))
(def students [{:name "Jack" :grade 90 :course "Math"}
{:name "Jill" :grade 88 :course "English"}
{:name "Joe" :grade 79 :course "English"}])
;
; (for [<var> <seq>]
; ...)
; - creates a new scope with the additional symbol binding for <var>.
; - each element in seq is processed exactly once
(for [x students]
(get x :name))
(for [x students]
(format "%s received %d%% for %s" (:name x) (:grade x) (:course x)))
;
; (for ...) is a data expression, so it can be used anywhere where
; a sequence is expected.
;
(pprint (for [x students]
(format "%s -> %d" (:name x) (:grade x))))
(println (clojure.string/join "\n" (for [x students]
(format "%s -> %d" (:name x) (:grade x)))))
;
; We can iterate through a hash-map as sequence of [key/value] pairs.
;
(def people {"Albert Einstein" {:profession "Physicist"
:date-of-birth {:month "March"
:day 17
:year 1879}}
"Elvis Presley" {:profession "Musician"
:date-of-birth {:month "January"
:day 8
:year 1935}}
"Martin Luther King Jr" {:profession "Minister",
:date-of-birth {:month "January"
:day 15
:year 1929}}})
(count courses)
(for [[name info] courses]
(format "%s worked as a %s" name (:profession info)))
;
; Idiomatic Clojure -- use functions
;
(defn pad-value [x width]
(let [string (str x)
padding (- width (count string))]
(str x (clojure.string/join "" (repeat padding " ")))))
(pad-value 3.1415 10)
(defn format-info [name info]
(let [prof (:profession info)
month (get-in info [:date-of-birth :month])
year (get-in info [:date-of-birth :year])]
(str "| "
(pad-value name 30)
"| "
(pad-value prof 20)
"| "
(pad-value (format "%d/%s" year month) 20)
"|")))
(format-info "Albert Einstein" (get people "Albert Einstein"))
(println
(clojure.string/join
"\n"
(for [[name info] people]
(format-info name info))))
;
; for supports iteration over
; multiple sequences using
; variable bindings
;
(for [x (range 5)
y (range x)]
[x y])
;
; (for ...) allows filtering
;
(for [x (range 5)
y (range x)
:when (odd? (+ x y))]
[x y])
;; about 3 seconds
(time (apply + (for [i (range 1e8)] (Math/pow i 2))))
(time (def lots-of-squares (for [i (range 1e8)] (Math/pow i 2))))
(take 10 lots-of-squares)