This commit is contained in:
Manas Karekar 2013-03-03 17:18:54 -08:00
commit 7b633f4529
10 changed files with 87 additions and 85 deletions

View file

@ -68,7 +68,9 @@ The output is telling you that you have a failing test in the file named
`01_equalities.clj`, on line 3. So you just need to open that file up and make
it pass! You'll always be filling in the blanks to make tests pass.
Sometimes there could be several correct answers (or even an infinite number):
any of them will work in these cases.
any of them will work in these cases. Some tests will pass even if you replace
the blanks with whitespace or nothing instead of the expected answer. Make sure
you give one correct expression to replace each blank.
The koans differ from normal TDD in that the tests are already written for you,
so you'll have to pay close attention to the failure messages, because up until

View file

@ -1,21 +1,21 @@
(meditations
"We shall contemplate truth by testing reality, via equality"
(= __ true)
(= true true)
"To understand reality, we must compare our expectations against reality"
(= __ (+ 1 1))
(= 2 (+ 1 1))
"You can test equality of many things"
(= (+ 3 4) __ (+ 2 __))
(= (+ 3 4) 7 (+ 2 5))
"Some things may appear different, but be the same"
(= 2 2/1 __)
(= 2 2/1 4/2)
"You cannot generally float to heavens of integers"
(= __ (= 2 2.0))
(= false (= 2 2.0))
"But a looser equality is also possible"
(== 2.0 2 __)
(== 2.0 2 4/2)
"When things cannot be equal, they must be different"
(not= :fill-in-the-blank __))
(not= :fill-in-the-blank :not))

View file

@ -1,34 +1,34 @@
(meditations
"Lists can be expressed by function or a quoted form"
(= '(__ __ __ __ __) (list 1 2 3 4 5))
(= '(1 2 3 4 5) (list 1 2 3 4 5))
"They are Clojure seqs (sequences), so they allow access to the first"
(= __ (first '(1 2 3 4 5)))
(= 1 (first '(1 2 3 4 5)))
"As well as the rest"
(= __ (rest '(1 2 3 4 5)))
(= [2 3 4 5] (rest '(1 2 3 4 5)))
"The rest when nothing is left is empty"
(= __ (rest '(100)))
(= [] (rest '(100)))
"And construction by adding an element to the front is simple"
(= __ (cons :a '(:b :c :d :e)))
(= '(:a :b :c :d :e) (cons :a '(:b :c :d :e)))
"Conjoining an element to a list can be done in the reverse order"
(= __ (conj '(:a :b :c :d :e) 0))
(= '(0 :a :b :c :d :e) (conj '(:a :b :c :d :e) 0))
"You can use a list like a stack to get the first element"
(= __ (peek '(:a :b :c :d :e)))
(= :a (peek '(:a :b :c :d :e)))
"Or the others"
(= __ (pop '(:a :b :c :d :e)))
(= '(:b :c :d :e) (pop '(:a :b :c :d :e)))
"But watch out if you try to pop nothing"
(= __ (try
(= "No dice!" (try
(pop '())
(catch IllegalStateException e "No dice!")))
"The rest of nothing isn't so strict"
(= __ (try
(= () (try
(rest '())
(catch IllegalStateException e "No dice!"))))

View file

@ -1,33 +1,33 @@
(meditations
"You can use vectors in clojure to create an 'Array' like structure"
(= __ (count [42]))
(= 1 (count [42]))
"You can create a vector in several ways"
(= __ (vec nil))
(= [] (vec nil))
"And populate it in either of these ways"
(= __ (vec '(1)))
(= [1] (vec '(1)))
"There is another way as well"
(= __ (vector nil))
(= [nil] (vector nil))
"But you can populate it with any number of elements at once"
(= [1 __] (vec '(1 2)))
(= [1 2] (vec '(1 2)))
"And add to it as well"
(= __ (conj (vec nil) 333))
(= [333] (conj (vec nil) 333))
"You can get the first element of a vector like so"
(= __ (first [:peanut :butter :and :jelly]))
(= :peanut (first [:peanut :butter :and :jelly]))
"And the last in a similar fashion"
(= __ (last [:peanut :butter :and :jelly]))
(= :jelly (last [:peanut :butter :and :jelly]))
"Or any index if you wish"
(= __ (nth [:peanut :butter :and :jelly] 3))
(= :jelly (nth [:peanut :butter :and :jelly] 3))
"You can also slice a vector"
(= __ (subvec [:peanut :butter :and :jelly] 1 3))
(= [:butter :and] (subvec [:peanut :butter :and :jelly] 1 3))
"Equality with collections is in terms of values"
(= (list 1 2 3) (vector 1 2 __)))
(= (list 1 2 3) (vector 1 2 3)))

View file

@ -1,18 +1,18 @@
(meditations
"You can create a set in two ways"
(= #{} (set __))
(= #{} (set nil))
"They are another important data structure in clojure"
(= __ (count #{1 2 3}))
(= 3 (count #{1 2 3}))
"Remember that a set is a 'set'"
(= __ (set '(1 1 2 2 3 3 4 4 5 5)))
(= #{1 2 3 4 5} (set '(1 1 2 2 3 3 4 4 5 5)))
"You can ask clojure for the union of two sets"
(= __ (clojure.set/union #{1 2 3 4} #{2 3 5}))
(= #{1 2 3 4 5} (clojure.set/union #{1 2 3 4} #{2 3 5}))
"And also the intersection"
(= __ (clojure.set/intersection #{1 2 3 4} #{2 3 5}))
(= #{2 3} (clojure.set/intersection #{1 2 3 4} #{2 3 5}))
"But don't forget about the difference"
(= __ (clojure.set/difference #{1 2 3 4 5} #{2 3 5})))
(= #{1 4} (clojure.set/difference #{1 2 3 4 5} #{2 3 5})))

View file

@ -1,50 +1,50 @@
(meditations
"There are two ways to create maps"
(= __ (hash-map))
(= {} (hash-map))
"Maps in clojure associate keys with values"
(= __ (count (hash-map)))
(= 0 (count (hash-map)))
"A value must be supplied for each key"
(= {:a 1} (hash-map :a __))
(= {:a 1} (hash-map :a 1))
"The size is the number of entries"
(= __ (count {:a 1 :b 2}))
(= 2 (count {:a 1 :b 2}))
"You can look up the value for a given key"
(= __ (get {:a 1 :b 2} :b))
(= 2 (get {:a 1 :b 2} :b))
"Maps can be used as lookup functions"
(= __ ({:a 1 :b 2} :a))
(= 1 ({:a 1 :b 2} :a))
"And so can keywords"
(= __ (:a {:a 1 :b 2}))
(= 1 (:a {:a 1 :b 2}))
"But map keys need not be keywords"
(= __ ({2006 "Torino" 2010 "Vancouver" 2014 "Sochi"} 2010))
(= "Vancouver" ({2006 "Torino" 2010 "Vancouver" 2014 "Sochi"} 2010))
"You may not be able to find an entry for a key"
(= __ (get {:a 1 :b 2} :c))
(= nil (get {:a 1 :b 2} :c))
"But you can provide your own default"
(= __ (get {:a 1 :b 2} :c :key-not-found))
(= :key-not-found (get {:a 1 :b 2} :c :key-not-found))
"You can find out if a key is present"
(= __ (contains? {:a nil :b nil} :b))
(= true (contains? {:a nil :b nil} :b))
"Or if it is missing"
(= __ (contains? {:a nil :b nil} :c))
(= false (contains? {:a nil :b nil} :c))
"Maps are immutable, but you can create a new, 'changed' version"
(= {1 "January" 2 __} (assoc {1 "January" } 2 "February"))
(= {1 "January" 2 "February"} (assoc {1 "January" } 2 "February"))
"You can also 'remove' an entry"
(= {__ __} (dissoc {1 "January" 2 "February"} 2))
(= {1 "January"} (dissoc {1 "January" 2 "February"} 2))
"Often you will need to get the keys (which will be in hash order)"
(= (list __ __ __)
(= (list 2006 2010 2014)
(sort (keys {2006 "Torino" 2010 "Vancouver" 2014 "Sochi"})))
"Or the values"
(= (list "Sochi" "Torino" __)
(= (list "Sochi" "Torino" "Vancouver")
(sort (vals {2006 "Torino" 2010 "Vancouver" 2014 "Sochi"}))))

View file

@ -5,25 +5,25 @@
(meditations
"Functions are often defined before they are used"
(= __ (multiply-by-ten 2))
(= 20 (multiply-by-ten 2))
"But they can also be defined inline"
(= __ ((fn [n] (* __ n)) 2))
(= 20 ((fn [n] (* 10 n)) 2))
"Or using even shorter syntax"
(= __ (#(* 15 %) __))
(= 20 (#(* 10 %) 2))
"Short anonymous functions may take multiple arguments"
(= __ (#(+ %1 %2 %3) 4 5 6))
(= 15 (#(+ %1 %2 %3) 4 5 6))
"One function can beget another"
(= __ ((fn []
((fn [a b] (__ a b))
(= 9 ((fn []
((fn [a b] (+ a b))
4 5))))
"Higher-order functions take function arguments"
(= 25 (___
(= 25 ((fn [func] (func 5))
(fn [n] (* n n))))
"But they are often better written using the names of functions"
(= 25 (___ square)))
(= 25 ((defn square5 [square] (square 5)) square)))

View file

@ -9,38 +9,38 @@
(meditations
"You will face many decisions"
(= __ (if (false? (= 4 5))
(= :a (if (false? (= 4 5))
:a
:b))
"Some of them leave you no alternative"
(= __ (if (> 4 3)
(= [] (if (> 4 3)
[]))
"And in such a situation you may have nothing"
(= __ (if (nil? 0)
(= nil (if (nil? 0)
[:a :b :c]))
"In others your alternative may be interesting"
(= :glory (if (not (empty? ()))
:doom
__))
:glory))
"You may have a multitude of possible paths"
(let [x 5]
(= :your-road (cond (= x __) :road-not-taken
(= x __) :another-road-not-taken
:else __)))
(= :your-road (cond (= x 2) :road-not-taken
(= x 3) :another-road-not-taken
:else :your-road)))
"Or your fate may be sealed"
(= __ (if-not (zero? __)
(= 'doom (if-not (zero? 1)
'doom
'doom))
"In case of emergency, sound the alarms"
(= :sirens
(explain-defcon-level __))
(explain-defcon-level :cocked-pistol))
"But admit it when you don't know what to do"
(= __
(= :say-what?
(explain-defcon-level :yo-mama)))

View file

@ -1,32 +1,32 @@
(meditations
"The map function relates a sequence to another"
(= [__ __ __] (map (fn [x] (* 4 x)) [1 2 3]))
(= [4 8 12] (map (fn [x] (* 4 x)) [1 2 3]))
"You may create that mapping"
(= [1 4 9 16 25] (map (fn [x] __) [1 2 3 4 5]))
(= [1 4 9 16 25] (map (fn [x] (* x x)) [1 2 3 4 5]))
"Or use the names of existing functions"
(= __ (map nil? [:a :b nil :c :d]))
(= [false false true false false] (map nil? [:a :b nil :c :d]))
"A filter can be strong"
(= __ (filter (fn [x] false) '(:anything :goes :here)))
(= [] (filter (fn [x] false) '(:anything :goes :here)))
"Or very weak"
(= __ (filter (fn [x] true) '(:anything :goes :here)))
(= [:anything :goes :here] (filter (fn [x] true) '(:anything :goes :here)))
"Or somewhere in between"
(= [10 20 30] (filter (fn [x] __) [10 20 30 40 50 60 70 80]))
(= [10 20 30] (filter (fn [x] (< x 40)) [10 20 30 40 50 60 70 80]))
"Maps and filters may be combined"
(= [10 20 30] (map (fn [x] __) (filter (fn [x] __) [1 2 3 4 5 6 7 8])))
(= [10 20 30] (map (fn [x] (* 10 x)) (filter (fn [x] (< x 4)) [1 2 3 4 5 6 7 8])))
"Reducing can increase the result"
(= __ (reduce (fn [a b] (* a b)) [1 2 3 4]))
(= 24 (reduce (fn [a b] (* a b)) [1 2 3 4]))
"You can start somewhere else"
(= 2400 (reduce (fn [a b] (* a b)) __ [1 2 3 4]))
(= 2400 (reduce (fn [a b] (* a b)) 100 [1 2 3 4]))
"Numbers are not the only things one can reduce"
(= "longest" (reduce (fn [a b]
(if (< __ __) b a))
(if (< (count a) (count b)) b a))
["which" "word" "is" "longest"])))

View file

@ -7,19 +7,19 @@
"!")))
(defmulti diet (fn [x] (:eater x)))
(defmethod diet :herbivore [a] __)
(defmethod diet :carnivore [a] __)
(defmethod diet :default [a] __)
(defmethod diet :herbivore [a] (str (:name a) " eats veggies."))
(defmethod diet :carnivore [a] (str (a :name) " eats animals."))
(defmethod diet :default [a] (str "I don't know what " (:name a) " eats."))
(meditations
"Some functions can be used in different ways - with no arguments"
(= __ (hello))
(= "Hello World!" (hello))
"With one argument"
(= __ (hello "world"))
(= "Hello, you silly world." (hello "world"))
"Or with many arguments"
(= __
(= "Hello to this group: Peter, Paul, Mary!"
(hello "Peter" "Paul" "Mary"))
"Multimethods allow more complex dispatching"