   (:require [midje.sweet :refer :all]))
 
 (facts  "pure functions:"
-  (fact (get [:chumbawumba] 0)
+  (fact
+    (get [:chumbawumba] 0)
     => :chumbawumba)
-  (fact (reduce + [1 10 5])
+  (fact
+    (reduce + [1 10 5])
     => 16)
-  (fact (str "wax on " "wax off")
+  (fact
+    (str "wax on " "wax off")
     => "wax on wax off"))
 
 (facts "pure functions are refentially transparent"
-  (fact (+ 1 2)
+  (fact
+    (+ 1 2)
     => 3))
 
 (defn wisdom
+  "the string ', Daniel-san' is immutable"
   [words]
   (str words ", Daniel-san"))
 
-(fact (wisdom "Always bathe on Fridays")
+(fact
+  (wisdom "Always bathe on Fridays")
   => "Always bathe on Fridays, Daniel-san")
 
 ;; always gives a differen result so not referntially transperent

(fact (sum-times2' 1 2 3)
  => 12)

;;;;;;;;;;;;;;;;;;;;
;; memoization

(defn sleepy-identity
  "returns the given value after a 1 second 'calculation'"

  [text]
  (s/replace (s/trim text) #"lol" "LOL"))

(fact
  (clean "My boa constrictor is so sassy lol!  ")
  => "My boa constrictor is so sassy LOL!")

;; use a chain of function calls instead of progressively mutating an object


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; cool things to do with functions
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(fact "chaining function is pretty common style so function called 'comp'"
  ((comp s/lower-case s/trim) " Unclean string ")
  => "unclean string")

;; 'def' create a function
(def my-lower-trim-1 (comp s/lower-case s/trim))
(fact
  (my-lower-trim-1  " Unclean string ")
  => "unclean string")

;; an implementation of 'comp' that composes two functions
(defn two-comp
  [f g]
  (fn [& args]
    (f (apply g args))))

(def my-lower-trim-2 (two-comp s/lower-case s/trim))

(fact
  (my-lower-trim-2 " Unclean string  ")
  => "unclean string")

(def sum-times2 (two-comp  #(* 2 %) +))

(fact
  (sum-times2 1 2 3)
  => 12)

;; define a new version of 'comp'
(defn my-comp
  [f & funs]
  (if (empty? funs) f    ;; base case - returned composed function
      (recur (fn [& args]
                 (f (apply (first funs) args)))
               (rest funs))))

(fact "works like two-comp"
  ((my-comp s/lower-case s/trim) " Unclean string ")
  => "unclean string")

(fact "works like regular 'comp'"
  ((my-comp s/reverse s/lower-case s/trim) " Unclean string ")
  => "gnirts naelcnu")

(def sum-times2' (two-comp  #(* 2 %) +))
