(when-let bindings & body)
bindings => binding-form test When test is true, evaluates body with binding-form bound to the value of test
;; Very useful when working with sequences. Capturing the return value
;; of `seq` brings a performance gain in subsequent `first`/`rest`/`next`
;; calls. Also the block is guarded by `nil` punning.
(defn drop-one
[coll]
(when-let [s (seq coll)]
(rest s)))
user=> (drop-one [1 2 3])
(2 3)
user=> (drop-one [])
nil
;; See examples for "if" explaining Clojure's idea of logical true
;; and logical false.
;; Works well with collections
(def x {:whatever 1})
(when-let [value (:whatever x)]
(println "x+1 = " (inc value)))
;; Prints: "x+1 = 2"
;; when-let multiple bindings version
(defmacro when-let*
([bindings & body]
(if (seq bindings)
`(when-let [~(first bindings) ~(second bindings)]
(when-let* ~(drop 2 bindings) ~@body))
`(do ~@body))))
(when-let* [a 1
b 2
c (+ a b)]
(println "yeah!")
c)
;;=>yeah!
;;=>3
(when-let* [a 1
b nil
c 3]
(println "damn! b is nil")
a)
;;=>nil
;; test is evaluated before values are bound to binding, so destructuring works
(when-let [[a] nil] [a])
=> nil
(when-let [[a] [:a]] [a])
=> [:a]
(when-let [[a] []] [a])
=> [nil]