You're viewing version 1.2.0 of if-let. The latest stable version of Clojure Core is 1.3.0.
1.2.0 Arrow_down_16x16

if-let

clojure.core

  • (if-let bindings then)
  • (if-let bindings then else & oldform)
bindings => binding-form test

If test is true, evaluates then with binding-form bound to the value of
test, if not, yields else

5 Examples top

  • user=> (defn sum-even-numbers [nums]
             (if-let [nums (seq (filter even? nums))]
               (reduce + nums)
               "No even numbers found."))
    #'user/sum-even-numbers
    
    user=> (sum-even-numbers [1 3 5 7 9])
    "No even numbers found."
    
    user=> (sum-even-numbers [1 3 5 7 9 10 12])
    22
    
  • user=> (if-let [x false y true]
             "then"
             "else")
    java.lang.IllegalArgumentException: if-let requires exactly 2 forms in binding vector (NO_SOURCE_FILE:1)
    
    user=> (defn if-let-demo [arg]
             (if-let [x arg]
               "then"
               "else"))
    
    user=> (if-let-demo 1) ; anything except nil/false
    "then"
    user=> (if-let-demo nil)
    "else"
    user=> (if-let-demo false)
    "else"
    
  • ; 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.
  • ;; See examples for "if" explaining Clojure's idea of logical true
    ;; and logical false.
  • ;;; 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
    
Log in to add / edit an example.

See Also top

Log in to add a see also.

Plus_12x12 Minus_12x12 Source clojure/core.clj:1403 top

(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 if-let
     (and (vector? bindings) (nil? oldform)) "a vector for its binding"
     (= 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)))))
Vars in clojure.core/if-let: = and count defmacro let nil? vector? apply concat list seq vector

Comments top

1 comment(s) for if-let.

The difference between when-let and if-let is that when-let doesn't have an else clause and and also accepts multiple forms so you don't need to use a (do...).

Log in to add a comment.