Functions in Depth

;; Anonymous functions
(fn [x] (* x x))
#(* % %)                              ; reader shorthand
#(+ %1 %2)
#(apply + %&)                         ; rest args
((fn [x y] (+ x y)) 1 2)              ; 3

;; Multi-arity
(defn greet
  ([] (greet "World"))
  ([name] (greet name "Hello"))
  ([name greeting] (str greeting ", " name "!")))
(greet)                               ; "Hello, World!"

;; Variadic
(defn sum [& nums] (apply + nums))
(sum 1 2 3 4)                         ; 10

;; Keyword arguments (1.11+: pass a trailing map or key-value pairs)
(defn connect [host & {:keys [port timeout] :or {port 80 timeout 5000}}]
  (str host ":" port " (timeout " timeout ")"))
(connect "localhost" :port 8080)
(connect "localhost" {:port 8080})    ; 1.11+

;; Pre/post conditions
(defn safe-sqrt [x]
  {:pre [(>= x 0)]
   :post [(>= % 0)]}
  (Math/sqrt x))

;; Higher-order functions
(map inc [1 2 3])                     ; (2 3 4)
(filter even? (range 10))             ; (0 2 4 6 8)
(reduce + [1 2 3 4])                  ; 10
(apply max [3 9 2])                   ; 9
(comp inc #(* 2 %))                   ; composition: right to left
((comp inc #(* 2 %)) 5)               ; 11
((partial + 10) 5)         
…