(if (pos? 1)
"one is positive"
"or is it?")
;=> "one is positive"
Control your own destiny or someone else will.
(if (pos? 1)
"one is positive"
"or is it?")
;=> "one is positive"Chooses between two options
Returns a result
Only one branch is evaluated
A function call evaluates all arguments
Booleans: true and false
nil means nothing and is considered false in logical tests
Anything else is truthy
(if 5
"it's five!"
"no problem")
;=> "it's five!" (if (pos? 1)
(do (prn "hi")
"one is positive")
"or is it?")
;;; "hi"
;=> "one is positive" (when (pos? 1)
(prn "multiple expressions allowed")
:ok)
;;; multiple expressions allowed
;=> :okWhen test fails, nothing is evaluated
When test passes, the entire body is evaluated
Returns the last expression as a result
(def x {:cake 1})
(cond (= x 1) "one"
(= x :cake) "the cake is a lie"
(map? x) "it's a map!"
:else "not sure what it is")
;=> "it's a map!"Multiple branches
:else is not special, keywords are truthy
See also condp and case
Built in primitives, not functions
def, let, quote and fn are special forms
Arguments are not evaluated
(if (= 1 2)
(prn "a")
(prn "b"))
;;; "b"
;=> nil (defn if-fn [condition a b]
(if condition a b))
(if-fn (= 1 2)
(prn "a")
(prn "b"))
;;; a
;;; b
;=> nilor is a macro
(or true (println "Hello"))
;=> trueArguments are not evaluated
Macros are used to implement and extend Clojure syntax
(or true false)
Expands to:
(let [a true]
(if a
a
(let [b false]
(if b
b))))) (apply or [true false true])
;;; CompilerException: Can't take value of a macro (apply if [true :a :b])
;;; CompilerException: Unable to resolve symbol: if| Macros cannot be passed as arguments to functions |
Remember the special forms:
if, do, let, quote, var, fn, loop, recur, throw, try
Control flow forms: cond, or, and, when
Navigate to source: def, defn, defmacro
See :macro in Metadata
Documentation
| Writing macros is covered later in the course |
(defn sum-up [coll result]
(if (empty? coll)
result
(sum-up (rest coll)
(+ result (first coll)))))Functions that invoke themselves are recursive
Recursion without consuming the stack
(defn sum-up-with-recur [coll result]
(if (empty? coll)
result
(recur (rest coll) (+ result (first coll)))))Recur can only occur where a function returns
Current frame will return the result of the next call
No further calculations needed
Current frame can be released
(loop [a 0
b 1]
(if (< b 1000)
(recur b (+ a b))
a))Loop establishes bindings
Allows recur to the start of the loop
Special forms try catch finally and throw
(try
(inc "cat")
(catch Exception e
(println "cat cannot be incremented"))
(finally
(println "always"))See manual end of section 5
(def grade [score]
(cond (>= score 90) "A"
(>= score 80) "B"
(>= score 70) "C"
(>= score 60) "D"
:else "F"))(deftest grade-test (is (= "B" (grade 85))))
(defn factorial [n]
(loop [acc 1
x n]
(if (<= x 1)
acc
(recur (* acc x) (dec x)))))(deftest factorial-test (is (= 120 (factorial 5))))
(defn factorial2
([n] (factorial2 1 n))
([acc n]
(if (<= n 1)
acc
(recur (* acc n) (dec n)))))(deftest factorial2-test (is (= 120 (factorial2 5))))
(defn fib [limit]
(loop [a 1
b 1]
(if (>= b limit)
a
(recur b (+ a b)))))(deftest fib-test (is (= 89 (fib 100))))