store/[org.clojure/clojure "1.8.0"] clj::clojure.core/if-let

Community Documentation

Edit

Arities

[bindings then]
[bindings then else & oldform]

Docstring

bindings => binding-form test

If test is truthy, evaluates the then expression with binding-form bound to the result of the test, if not, yields the result of the else expression.

Source

(defmacro if-let
  "bindings => binding-form test

  If test is true, evaluates then with binding-form bound to the value of 
  test, if not, yields else"
  {:added "1.0"}
  ([bindings then]
   `(if-let ~bindings ~then nil))
  ([bindings then else & oldform]
   (assert-args
     (vector? bindings) "a vector for its binding"
     (nil? oldform) "1 or 2 forms after binding vector"
     (= 2 (count bindings)) "exactly 2 forms in binding vector")
   (let [form (bindings 0) tst (bindings 1)]
     `(let [temp# ~tst]
        (if temp#
          (let [~form temp#]
            ~then)
          ~else)))))

Example 1

Edit
(if-let [x false y true]
  "then"
  "else")
;; => java.lang.IllegalArgumentException: if-let requires exactly 2 forms in binding vector (NO_SOURCE_FILE:1)

(defn if-let-demo [arg]
  (if-let [x arg]
    "then"
    "else"))

(if-let-demo 1) ; anything except nil/false
;; => "then"

(if-let-demo nil)
;; => "else"

(if-let-demo false)
;; => "else"

Example 2

Edit
(defn sum-even-numbers [nums]
  (if-let [nums (seq (filter even? nums))]
    (reduce + nums)
    "No even numbers found."))
;; => #'user/sum-even-numbers

(sum-even-numbers [1 3 5 7 9])
;; => "No even numbers found."

(sum-even-numbers [1 3 5 7 9 10 12])
;; => 22

Example 3

Edit
;; See examples for "if" explaining Clojure's idea of logical true
;; and logical false.

Example 4

Edit
;;; with distructuring binding

;; successful case
(if-let [[w n] (re-find #"a(\d+)x" "aaa123xxx")]
  [w n]
  :not-found)  ;=> ["a123x" "123"]

;; unsuccessful case
(if-let [[w n] (re-find #"a(\d+)x" "bbb123yyy")]
  [w n]
  :not-found) ;=> :not-found

;; same as above
(if-let [[w n] nil]
  [w n]
  :not-found) ;=> :not-found

;; on Map
(if-let [{:keys [a b]} nil]
  [a b]
  :not-found) ;=> :not-found

Example 5

Edit
; This macro is nice when you need to calculate something big. And you need 
; to use the result but only when it's true:

(if-let [life (meaning-of-life 12)]
  life
  (if-let [origin (origin-of-life 1)]
    origin
    (if-let [shot (who-shot-jr 5)]
      block-sol
      42)))

; As you can see in the above example it will return the answer 
; to the question only if the answer is not nil. If the answer
; is nil it will move to the next question. Until finally it
; gives up and returns 42.

Uses on crossclj