when-let

added
1.0

ns
clojure.core

type
macro

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