Browse files

Created cascalog-koans.

  • Loading branch information...
1 parent 3cca560 commit 389daa55cd3f492352e1b1dee86707327cedb1ef @sritchie sritchie committed Nov 20, 2011
View
1 .gitignore
@@ -4,3 +4,4 @@ lib
releases
*.jar
.DS_Store
+.lein-deps-sum
View
9 project.clj
@@ -1,6 +1,9 @@
-(defproject functional-koans "0.4.5"
- :description "The functional koans"
+(defproject cascalog-koans "0.4.5"
+ :description "Koans for Cascalog."
:dependencies [[org.clojure/clojure "1.3.0"]
+ [cascalog "1.8.4"]
[fresh "1.0.2"]
[jline "0.9.94" :exclusions [junit]]]
- :dev-dependencies [[swank-clojure "1.3.0" :exclusions [org.clojure/clojure]]])
+ :dev-dependencies [[org.apache.hadoop/hadoop-core "0.20.2-dev"]
+ [swank-clojure "1.4.0-SNAPSHOT"
+ :exclusions [org.clojure/clojure]]])
View
14 script/deploy.sh
@@ -1,14 +0,0 @@
-#!/bin/sh
-
-git push
-mkdir -p releases
-zip -r releases/clojure-koans-`date +"%Y-%m-%d_%H-%M"`.zip \
- . \
- -x "./.git/*" \
- -x "releases/*"
-
-echo
-echo "Don't forget to upload the zipfile"
-echo " to https://github.com/functional-koans/clojure-koans/downloads"
-echo `ls -t releases/clojure-koans-*.zip | head -n1`
-echo
View
4 script/run
@@ -1,6 +1,10 @@
#!/bin/sh
CLASSPATH=src
+for f in lib/dev/*.jar; do
+ CLASSPATH=$CLASSPATH:$f
+done
+
for f in lib/*.jar; do
CLASSPATH=$CLASSPATH:$f
done
View
4 script/test
@@ -1,6 +1,10 @@
#!/bin/sh
CLASSPATH=src
+for f in lib/dev/*.jar; do
+ CLASSPATH=$CLASSPATH:$f
+done
+
for f in lib/*.jar; do
CLASSPATH=$CLASSPATH:$f
done
View
30 src/koans/atoms.clj
@@ -1,30 +0,0 @@
-(def atomic-clock (atom 0))
-
-(meditations
- "Atoms are like refs"
- (= __ @atomic-clock)
-
- "You can change at the swap meet"
- (= __ (do
- (swap! atomic-clock inc)
- @atomic-clock))
-
- "Keep taxes out of this: swapping requires no transaction"
- (= 5 (do
- __
- @atomic-clock))
-
- "Any number of arguments might happen during a swap"
- (= __ (do
- (swap! atomic-clock + 1 2 3 4 5)
- @atomic-clock))
-
- "Atomic atoms are atomic"
- (= __ (do
- (compare-and-set! atomic-clock 100 :fin)
- @atomic-clock))
-
- "When your expectations are aligned with reality things, proceed that way"
- (= :fin (do
- (compare-and-set! __ __ __)
- @atomic-clock)))
View
46 src/koans/conditionals.clj
@@ -1,46 +0,0 @@
-(defn explain-defcon-level [exercise-term]
- (case exercise-term
- :fade-out :you-and-what-army
- :double-take :call-me-when-its-important
- :round-house :o-rly
- :fast-pace :thats-pretty-bad
- :cocked-pistol :sirens
- :say-what?))
-
-(meditations
- "You will face many decisions"
- (= __ (if (false? (= 4 5))
- :a
- :b))
-
- "Some of them leave you no alternative"
- (= __ (if (> 4 3)
- []))
-
- "And in such a situation you may have nothing"
- (= __ (if (nil? 0)
- [:a :b :c]))
-
- "In others your alternative may be interesting"
- (= :glory (if (not (empty? ()))
- :doom
- __))
-
- "You may have a multitude of possible paths"
- (let [x 5]
- (= :your-road (cond (= x __) :road-not-taken
- (= x __) :another-road-not-taken
- :else __)))
-
- "Or your fate may be sealed"
- (= __ (if-not (zero? __)
- 'doom
- 'doom))
-
- "In case of emergency, sound the alarms"
- (= :sirens
- (explain-defcon-level __))
-
- "But admit it when you don't know what to do"
- (= __
- (explain-defcon-level :yo-mama)))
View
32 src/koans/creating_functions.clj
@@ -1,32 +0,0 @@
-(defn square [x] (* x x))
-
-(meditations
- "One may know what they seek by knowing what they do not seek"
- (= [__ __ __] (let [not-a-symbol? (complement symbol?)]
- (map not-a-symbol? [:a 'b "c"])))
-
- "Praise and 'complement' may help you separate the wheat from the chaff"
- (= [:wheat "wheat" 'wheat]
- (let [not-nil? ___]
- (filter not-nil? [nil :wheat nil "wheat" nil 'wheat nil])))
-
- "Partial functions allow procrastination"
- (= 20 (let [multiply-by-5 (partial * 5)]
- (___ __)))
-
- "Don't forget: first things first"
- (= [__ __ __ __]
- (let [ab-adder (partial concat [:a :b])]
- (ab-adder [__ __])))
-
- "Functions can join forces as one 'composed' function"
- (= 25 (let [inc-and-square (comp square inc)]
- (inc-and-square __)))
-
- "Have a go on a double dec-er"
- (= __ (let [double-dec (comp dec dec)]
- (double-dec 10)))
-
- "Be careful about the order in which you mix your functions"
- (= 99 (let [square-and-dec ___]
- (square-and-dec 10))))
View
44 src/koans/datatypes.clj
@@ -1,44 +0,0 @@
-(defrecord Nobel [prize])
-(deftype Pulitzer [prize])
-
-(defprotocol Award
- (present [this recipient]))
-
-(defrecord Oscar [category]
- Award
- (present [this recipient]
- (print (str "Congratulations on your "
- (:category this) " Oscar, "
- recipient
- "!"))))
-
-(deftype Razzie [category]
- Award
- (present [this recipient]
- __))
-
-(meditations
- "Holding records is meaningful only when the record is worthy of you"
- (= __ (.prize (Nobel. "peace")))
-
- "Types are quite similar"
- (= __ (.prize (Pulitzer. "literature")))
-
- "Records may be treated like maps"
- (= __ (:prize (Nobel. "physics")))
-
- "While types may not"
- (= __ (:prize (Pulitzer. "poetry")))
-
- "Further study reveals why"
- (= __
- (map map? [(Nobel. "chemistry")
- (Pulitzer. "music")]))
-
- "Either sort of datatype can define methods in a protocol"
- (= __
- (with-out-str (present (Oscar. "Best Picture") "Evil Alien Conquerors")))
-
- "Surely we can implement our own by now"
- (= "You're really the Worst Picture, Final Destination 5... sorry."
- (with-out-str (present (Razzie. "Worst Picture") "Final Destination 5"))))
View
41 src/koans/destructuring.clj
@@ -1,41 +0,0 @@
-(def test-address
- {:street-address "123 Test Lane"
- :city "Testerville"
- :state "TX"})
-
-(meditations
- "Destructuring is an arbiter: it breaks up arguments"
- (= __ ((fn [[a b]] (str b a))
- [:foo :bar]))
-
- "Whether in function definitions"
- (= (str "First comes love, "
- "then comes marriage, "
- "then comes Clojure with the baby carriage")
- ((fn [[a b c]] __)
- ["love" "marriage" "Clojure"]))
-
- "Or in let expressions"
- (= "Rich Hickey aka The Clojurer aka Go Time aka Macro Killah"
- (let [[first-name last-name & aliases]
- (list "Rich" "Hickey" "The Clojurer" "Go Time" "Macro Killah")]
- __))
-
- "You can regain the full argument if you like arguing"
- (= {:original-parts ["Steven" "Hawking"] :named-parts {:first "Steven" :last "Hawking"}}
- (let [[first-name last-name :as full-name] ["Steven" "Hawking"]]
- __))
-
- "Break up maps by key"
- (= "123 Test Lane, Testerville, TX"
- (let [{street-address :street-address, city :city, state :state} test-address]
- __))
-
- "Or more succinctly"
- (= "123 Test Lane, Testerville, TX"
- (let [{:keys [street-address __ __]} test-address]
- __))
-
- "All together now!"
- (= "Test Testerson, 123 Test Lane, Testerville, TX"
- (___ ["Test" "Testerson"] test-address)))
View
21 src/koans/equalities.clj
@@ -1,21 +0,0 @@
-(meditations
- "We shall contemplate truth by testing reality, via equality."
- (= __ true)
-
- "To understand reality, we must compare our expectations against reality."
- (= __ (+ 1 1))
-
- "You can test equality of many things"
- (= (+ 3 4) __ (+ 2 __))
-
- "Some things may appear different, but be the same"
- (= 2 2/1 __)
-
- "You cannot generally float to heavens of integers"
- (= __ (= 2 2.0))
-
- "But a looser equality is also possible"
- (== 2.0 2 __)
-
- "When things cannot be equal, they must be different"
- (not= :fill-in-the-blank __))
View
29 src/koans/functions.clj
@@ -1,29 +0,0 @@
-(defn multiply-by-ten [n]
- (* 10 n))
-
-(defn square [n] (* n n))
-
-(meditations
- "Functions are often defined before they are used"
- (= __ (multiply-by-ten 2))
-
- "But they can also be defined inline"
- (= __ ((fn [n] (* __ n)) 2))
-
- "Or using even shorter syntax"
- (= __ (#(* 15 %) __))
-
- "Short anonymous functions may take multiple arguments"
- (= __ (#(+ %1 %2 %3) 4 5 6))
-
- "One function can beget another"
- (= __ ((fn []
- ((fn [a b] (__ a b))
- 4 5))))
-
- "Higher-order functions take function arguments"
- (= 25 (___
- (fn [n] (* n n))))
-
- "But they are often better written using the names of functions"
- (= 25 (___ square)))
View
32 src/koans/higher_order_functions.clj
@@ -1,32 +0,0 @@
-(meditations
- "The map function relates a sequence to another"
- (= [__ __ __] (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]))
-
- "Or use the names of existing functions"
- (= __ (map nil? [:a :b nil :c :d]))
-
- "A filter can be strong"
- (= __ (filter (fn [x] false) '(:anything :goes :here)))
-
- "Or very weak"
- (= __ (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]))
-
- "Maps and filters may be combined"
- (= [10 20 30] (map (fn [x] __) (filter (fn [x] __) [1 2 3 4 5 6 7 8])))
-
- "Reducing can increase the result"
- (= __ (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]))
-
- "Numbers are not the only things one can reduce"
- (= "longest" (reduce (fn [a b]
- (if (< __ __) b a))
- ["which" "word" "is" "longest"])))
View
16 src/koans/java_interop.clj
@@ -1,16 +0,0 @@
-(meditations
- "You may have done more with Java than you know"
- (= __ (class "warfare")) ; hint: try typing (javadoc "warfare") in the REPL
-
- "The dot signifies easy and direct Java interoperation"
- (= __ (.toUpperCase "select * from"))
-
- "But instance method calls are very different from normal functions"
- (= ["SELECT" "FROM" "WHERE"] (map ___ ["select" "from" "where"]))
-
- "Constructing might be harder than breaking"
- (= 10 (let [latch (java.util.concurrent.CountDownLatch. __)]
- (.getCount latch)))
-
- "Static methods are slashing prices!"
- (== __ (Math/pow 2 10)))
View
25 src/koans/lazy_sequences.clj
@@ -1,25 +0,0 @@
-(meditations
- "There are a wide range of ways to generate a sequence"
- (= __ (range 1 5))
-
- "The range starts at the beginning by default"
- (= __ (range 5))
-
- "It's important to only take what you need from a big sequence"
- (= [0 1 2 3 4 5 6 7 8 9]
- (take __ (range 100)))
-
- "You can also limit results by dropping what you don't need"
- (= [95 96 97 98 99]
- (drop __ (range 100)))
-
- "Iteration provides an infinite lazy sequence"
- (= __ (take 20 (iterate inc 0)))
-
- "Repetition is key"
- (= [:a :a :a :a :a :a :a :a :a :a ]
- (repeat 10 __))
-
- "Iteration can be used for repetition"
- (= (repeat 100 :foo)
- (take 100 (iterate ___ :foo))))
View
34 src/koans/lists.clj
@@ -1,34 +0,0 @@
-(meditations
- "Lists can be expressed by function or a quoted form"
- (= '(__ __ __ __ __) (list 1 2 3 4 5))
-
- "They are Clojure seqs (sequences), so they allow access to the first"
- (= __ (first '(1 2 3 4 5)))
-
- "As well as the rest"
- (= __ (rest '(1 2 3 4 5)))
-
- "The rest when nothing is left is empty"
- (= __ (rest '(100)))
-
- "And construction by adding an element to the front is simple"
- (= __ (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))
-
- "You can use a list like a stack to get the first element"
- (= __ (peek '(:a :b :c :d :e)))
-
- "Or the others"
- (= __ (pop '(:a :b :c :d :e)))
-
- "But watch out if you try to pop nothing"
- (= __ (try
- (pop '())
- (catch IllegalStateException e "No dice!")))
-
- "The rest of nothing isn't so strict"
- (= __ (try
- (rest '())
- (catch IllegalStateException e "No dice!"))))
View
42 src/koans/macros.clj
@@ -1,42 +0,0 @@
-(defmacro hello [x]
- (str "Hello, " x))
-
-(defmacro infix [form]
- (list (second form) (first form) (nth form 2)))
-
-(defmacro infix-better [form]
- `(~(second form) ; Note the syntax-quote (`) and unquote (~) characters!
- __
- __ ))
-
-(defmacro r-infix [form]
- (cond (not (seq? form))
- __
- (= 1 (count form))
- `(r-infix ~(first form))
- :else
- (let [operator (second form)
- first-arg (first form)
- others __]
- `(~operator
- (r-infix ~first-arg)
- (r-infix ~others)))))
-
-(meditations
- "Macros are like functions created at compile time"
- (= __ (hello "Macros!"))
-
- "Can I haz some infix?"
- (= __ (infix (9 + 1)))
-
- "Remember, these are nothing but code transformations"
- (= __ (macroexpand '(infix (9 + 1))))
-
- "You can do better than that, hand crafting ftw!"
- (= __ (macroexpand '(infix-better (10 * 2))))
-
- "Things dont always work as you would like them to... "
- (= __ (macroexpand '(infix-better ( 10 + (2 * 3)))))
-
- "Really, you dont understand recursion until you understand recursion"
- (= 36 (r-infix (10 + (2 * 3) + (4 * 5)))))
View
50 src/koans/maps.clj
@@ -1,50 +0,0 @@
-(meditations
- "There are two ways to create maps"
- (= __ (hash-map))
-
- "Maps in clojure associate keys with values"
- (= __ (count (hash-map)))
-
- "A value must be supplied for each key"
- (= {:a 1} (hash-map :a __))
-
- "The size is the number of entries"
- (= __ (count {:a 1 :b 2}))
-
- "You can look up the value for a given key"
- (= __ (get {:a 1 :b 2} :b))
-
- "Maps can be used as lookup functions"
- (= __ ({:a 1 :b 2} :a))
-
- "And so can keywords"
- (= __ (:a {:a 1 :b 2}))
-
- "But map keys need not be keywords"
- (= __ ({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))
-
- "But you can provide your own default"
- (= __ (get {:a 1 :b 2} :c :key-not-found))
-
- "You can find out if a key is present"
- (= __ (contains? {:a nil :b nil} :b))
-
- "Or if it is missing"
- (= __ (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"))
-
- "You can also 'remove' an entry"
- (= {__ __} (dissoc {1 "January" 2 "February"} 2))
-
- "Often you will need to get the keys (which will be in hash order)"
- (= (list __ __ __)
- (sort (keys {2006 "Torino" 2010 "Vancouver" 2014 "Sochi"})))
-
- "Or the values"
- (= (list "Sochi" "Torino" __)
- (sort (vals {2006 "Torino" 2010 "Vancouver" 2014 "Sochi"}))))
View
51 src/koans/recursion.clj
@@ -1,51 +0,0 @@
-(defn is-even? [n]
- (if (= n 0)
- __
- (___ (is-even? (dec n)))))
-
-(defn is-even-bigint? [n]
- (loop [n n
- acc true]
- (if (= n 0)
- __
- (recur (dec n) (not acc)))))
-
-(defn recursive-reverse [coll]
- __)
-
-(defn factorial [n]
- __)
-
-(meditations
- "Recursion ends with a base case"
- (= true (is-even? 0))
-
- "And starts by moving toward that base case"
- (= false (is-even? 1))
-
- "Having too many stack frames requires explicit tail calls with recur"
- (= false (is-even-bigint? 100003N))
-
- "Reversing directions is easy when you have not gone far"
- (= '(1) (recursive-reverse [1]))
-
- "Yet more difficult the more steps you take"
- (= '(5 4 3 2 1) (recursive-reverse [1 2 3 4 5]))
-
- "Simple things may appear simple."
- (= 1 (factorial 1))
-
- "They may require other simple steps."
- (= 2 (factorial 2))
-
- "Sometimes a slightly bigger step is necessary"
- (= 6 (factorial 3))
-
- "And eventually you must think harder"
- (= 24 (factorial 4))
-
- "You can even deal with very large numbers"
- (< 1000000000000000000000000N (factorial 1000N))
-
- "But what happens when the machine limits you?"
- (< 1000000000000000000000000N (factorial 10000N)))
View
39 src/koans/refs.clj
@@ -1,39 +0,0 @@
-(def the-world (ref "hello"))
-(def bizarro-world (ref {}))
-
-(meditations
- "In the beginning, there was a word"
- (= __ (deref the-world))
-
- "You can get the word more succinctly, but it's the same"
- (= __ @the-world)
-
- "You can be the change you wish to see in the world."
- (= __ (do
- (dosync (ref-set the-world "better"))
- @the-world))
-
- "Alter where you need not replace"
- (= __ (let [exclamator (fn [x] (str x "!"))]
- (dosync
- (alter the-world exclamator)
- (alter the-world exclamator)
- (alter the-world exclamator))
- @the-world))
-
- "Don't forget to do your work in a transaction!"
- (= 0 (do __
- @the-world))
-
- "Functions passed to alter may depend on the data in the ref"
- (= 20 (do
- (dosync (alter the-world ___))))
-
- "Two worlds are better than one"
- (= ["Real Jerry" "Bizarro Jerry"]
- (do
- (dosync
- (ref-set the-world {})
- (alter the-world assoc :jerry "Real Jerry")
- (alter bizarro-world assoc :jerry "Bizarro Jerry")
- __))))
View
35 src/koans/runtime_polymorphism.clj
@@ -1,35 +0,0 @@
-(defn hello
- ([] "Hello World!")
- ([a] (str "Hello, you silly " a "."))
- ([a & more] (str "Hello to this group: "
- (apply str
- (interpose ", " (concat (list a) more)))
- "!")))
-
-(defmulti diet (fn [x] (:eater x)))
-(defmethod diet :herbivore [a] __)
-(defmethod diet :carnivore [a] __)
-(defmethod diet :default [a] __)
-
-(meditations
- "Some functions can be used in different ways - with no arguments"
- (= __ (hello))
-
- "With one argument"
- (= __ (hello "world"))
-
- "Or with many arguments"
- (= __
- (hello "Peter" "Paul" "Mary"))
-
- "Multimethods allow more complex dispatching"
- (= "Bambi eats veggies."
- (diet {:species "deer" :name "Bambi" :age 1 :eater :herbivore}))
-
- "Different methods are used depending on the dispatch function result"
- (= "Simba eats animals."
- (diet {:species "lion" :name "Simba" :age 1 :eater :carnivore}))
-
- "You may use a default method when no others match"
- (= "I don't know what Rich Hickey eats."
- (diet {:name "Rich Hickey"})))
View
32 src/koans/sequence_comprehensions.clj
@@ -1,32 +0,0 @@
-(meditations
- "Sequence comprehensions can bind each element in turn to a symbol"
- (= __
- (for [index (range 6)]
- index))
-
- "They can easily emulate mapping"
- (= '(0 1 4 9 16 25)
- (map (fn [index] (* index index))
- (range 6))
- (for [index (range 6)]
- __))
-
- "And also filtering"
- (= '(1 3 5 7 9)
- (filter odd? (range 10))
- (for [index __ :when (odd? index)]
- index))
-
- "And they trivially allow combinations of the two transformations"
- (= '(1 9 25 49 81)
- (map (fn [index] (* index index))
- (filter odd? (range 10)))
- (for [index (range 10) :when __]
- __))
-
- "More complex transformations can be formed with multiple binding forms"
- (= [[:top :left] [:top :middle] [:top :right]
- [:middle :left] [:middle :middle] [:middle :right]
- [:bottom :left] [:bottom :middle] [:bottom :right]]
- (for [row [:top :middle :bottom] column [:left :middle :right]]
- __)))
View
18 src/koans/sets.clj
@@ -1,18 +0,0 @@
-(meditations
- "You can create a set in two ways"
- (= #{} (set __))
-
- "They are another important data structure in clojure"
- (= __ (count #{1 2 3}))
-
- "Remember that a set is a 'set'"
- (= __ (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}))
-
- "And also the intersection"
- (= __ (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})))
View
8 src/koans/tuples.clj
@@ -0,0 +1,8 @@
+(def one-tuple [[1]])
+
+(meditations
+ "We shall contemplate truth by testing reality, via equality."
+ (= __ [["truth."]])
+
+ "To understand reality, we must compare our expectations against reality."
+ (?= __ (<- [?x] (one-tuple ?x))))
View
33 src/koans/vectors.clj
@@ -1,33 +0,0 @@
-(meditations
- "You can use vectors in clojure to create an 'Array' like structure"
- (= __ (count [42]))
-
- "You can create a vector in several ways"
- (= __ (vec nil))
-
- "And populate it in either of these ways"
- (= __ (vec '(1)))
-
- "There is another way as well"
- (= __ (vector nil))
-
- "But you can populate it with any number of elements at once"
- (= [1 __] (vec '(1 2)))
-
- "And add to it as well"
- (= __ (conj (vec nil) 333))
-
- "You can get the first element of a vector like so"
- (= __ (first [:peanut :butter :and :jelly]))
-
- "And the last in a similar fashion"
- (= __ (last [:peanut :butter :and :jelly]))
-
- "Or any index if you wish"
- (= __ (nth [:peanut :butter :and :jelly] 3))
-
- "You can also slice a vector"
- (= __ (subvec [:peanut :butter :and :jelly] 1 3))
-
- "Equality with collections is in terms of values"
- (= (list 1 2 3) (vector 1 2 __)))
View
222 src/path_to_answer_sheet.clj
@@ -1,208 +1,14 @@
(ns path-to-answer-sheet
- (:use [runner.koans :only [ordered-koans]]
- [path-to-enlightenment :only [meditations fancy-assert __ ___]]
+ (:use cascalog.api
+ [runner.koans :only [ordered-koans]]
+ [path-to-enlightenment :only [meditations fancy-assert ?= __ ___]]
[clojure.string :only [join split trim] :as string]))
(def answers
- {"equalities" {"__" [true
- 2
- 7
- 5
- 4/2
- false
- 6/3
- 3]}
-
- "lists" {"__" [1 2 3 4 5
- 1
- [2 3 4 5]
- ()
- [:a :b :c :d :e]
- [0 :a :b :c :d :e]
- :a
- [:b :c :d :e]
- "No dice!"
- ()]}
-
- "vectors" {"__" [1
- []
- [1]
- [nil]
- 2
- [333]
- :peanut
- :jelly
- :jelly
- [:butter :and]
- 3]}
-
- "sets" {"__" [nil
- 3
- #{1 2 3 4 5}
- #{1 2 3 4 5}
- #{2 3}
- #{1 4}]}
-
- "maps" {"__" [{}
- 0
- 1
- 2
- 2
- 1
- 1
- "Vancouver"
- nil
- :key-not-found
- true
- false
- "February"
- 1 "January"
- 2006 2010 2014
- "Vancouver"]}
-
- "functions" {"__" [20
- 10 5
- 30 2
- 15
- 20 '*]
- "___" ['(fn [f] (f 5))
- '(fn [f] (f 5))]}
-
- "conditionals" {"__" [:a
- []
- nil
- :glory
- 4 6 :your-road
- ''doom 0
- :cocked-pistol
- :say-what?]}
-
- "higher_order_functions" {"__" [4 8 12
- '(* x x)
- [false false true false false]
- ()
- [:anything :goes :here]
- '(< x 31)
- '(* 10 x) '(< x 4)
- 24
- 100
- '(count a) '(count b)]}
-
- "runtime_polymorphism" {"__" ['(str (:name a) " eats veggies.")
- '(str (:name a) " eats animals.")
- '(str "I don't know what " (:name a) " eats.")
- "Hello World!"
- "Hello, you silly world."
- "Hello to this group: Peter, Paul, Mary!" ]}
-
- "lazy_sequences" {"__" [[1 2 3 4]
- [0 1 2 3 4]
- 10
- 95
- '(range 20)
- :a]
- "___" ['(fn [x] :foo)]}
-
- "sequence_comprehensions" {"__" [[0 1 2 3 4 5]
- '(* index index)
- '(range 10)
- '(odd? index) '(* index index)
- '[row column]
- ]}
-
- "creating_functions" {"__" [true false true
- 4
- :a :b :c :d
- :c :d
- 4
- 8]
- "___" ['(complement nil?)
- 'multiply-by-5
- '(comp dec square)]}
-
- "recursion" {"__" [true
- 'acc
- '(loop [coll coll
- acc ()]
- (if (seq coll)
- (recur (rest coll) (conj acc (first coll)))
- acc))
- '(loop [n n
- acc 1]
- (if (zero? n)
- acc
- (recur (dec n) (* acc n))))]
- "___" ['not]}
-
- "destructuring" {"__" [":bar:foo"
- '(format (str "First comes %s, "
- "then comes %s, "
- "then comes %s with the baby carriage")
- a b c)
- '(apply str
- (interpose " "
- (apply list
- first-name
- last-name
- (interleave (repeat "aka") aliases))))
- '{:original-parts full-name
- :named-parts {:first first-name :last last-name}}
- '(str street-address ", " city ", " state)
- 'city 'state
- '(str street-address ", " city ", " state)]
- "___" ['(fn [[fname lname]
- {:keys [street-address city state]}]
- (str fname " " lname ", "
- street-address ", " city ", " state))
- ]}
- "refs" {"__" ["hello"
- "hello"
- "better"
- "better!!!"
- '(dosync (ref-set the-world 0))
- '(map :jerry [@the-world @bizarro-world])
- ]
- "___" ['(fn [x] (+ 20 x))]}
-
- "atoms" {"__" [0
- 1
- '(swap! atomic-clock (partial + 4))
- 20
- 20
- 'atomic-clock 20 :fin
- ]}
-
- "macros" {"__" ['~(first form)
- '~(nth form 2)
- 'form
- '(drop 2 form)
- "Hello, Macros!"
- 10
- ''(+ 9 1)
- ''(* 10 2)
- ''(+ 10 (2 * 3))]}
-
- "datatypes" {"__" ['(print
- (str "You're really the "
- (.category this)
- ", " recipient "... sorry."))
- "peace"
- "literature"
- "physics"
- nil
- [true false]
- (str "Congratulations on your Best Picture Oscar, "
- "Evil Alien Conquerors!")]}
-
- "java_interop" {"__" ['java.lang.String
- "SELECT * FROM"
- 10
- 1024
- ]
- "___" ['#(.toUpperCase %)
- ]
- }
-
+ {"tuples" {"__" [
+ [["truth."]]
+ [[1]]
+ ]}
})
(defn replace-with [s k replacements]
@@ -259,12 +65,12 @@
(defn ensure-passing-with-answers []
(try
(dorun (map
- (fn [koan]
- (load-string
- (-> (koan-text koan)
- (fill-in-answers koan "__")
- (fill-in-answers koan "___"))))
- ordered-koans))
+ (fn [koan]
+ (load-string
+ (-> (koan-text koan)
+ (fill-in-answers koan "__")
+ (fill-in-answers koan "___"))))
+ ordered-koans))
(println "\nAll tests pass after the answers are filled in.")
(catch Exception e
@@ -275,5 +81,3 @@
(defn run []
(ensure-failing-without-answers)
(ensure-passing-with-answers))
-
-
View
16 src/path_to_enlightenment.clj
@@ -1,19 +1,23 @@
(ns path-to-enlightenment
- (:use [runner.freshness :only [setup-freshener]])
+ (:use [cascalog.testing :only (test?-)]
+ [cascalog.util :only (defalias)]
+ [runner.freshness :only [setup-freshener]])
(:require [clojure.set]
[clojure.string]))
(def __ :fill-in-the-blank)
(def ___ (fn [& args] __))
+;; More concise for koans.
+(defalias ?= test?-)
+
(defmacro fancy-assert
([x] (fancy-assert x ""))
([x message]
- `(try
- (assert ~x ~message)
- (catch Exception e#
- (throw (Exception. (str '~message "\n" '~x )
- e#))))))
+ `(try (assert ~x ~message)
+ (catch Exception e#
+ (throw (Exception. (str '~message "\n" '~x )
+ e#))))))
(defmacro meditations [& forms]
(let [pairs (partition 2 forms)
View
52 src/runner/koans.clj
@@ -1,26 +1,10 @@
(ns runner.koans
(:use [clojure.java.io :only [file]]))
+;; Add more koan namespaces here.
(def ordered-koans
- ["equalities"
- "lists"
- "vectors"
- "sets"
- "maps"
- "functions"
- "conditionals"
- "higher_order_functions"
- "runtime_polymorphism"
- "lazy_sequences"
- "sequence_comprehensions"
- "creating_functions"
- "recursion"
- "destructuring"
- "refs"
- "atoms"
- "macros"
- "datatypes"
- "java_interop"])
+ ["tuples"
+ ])
(defn ordered-koan-paths []
(map (fn [koan-name]
@@ -38,20 +22,22 @@
(recur more)))))
(defn tests-pass? [file-path]
- (use '[path-to-enlightenment :only [meditations __ ___]])
- (try
- (load-file file-path)
- true
- (catch Exception e
- (println)
- (println "Problem in" file-path)
- (println "---------------------")
- (println "Assertion failed!")
- (let [actual-error (or (.getCause e) e)
- message (or (.getMessage actual-error)
- (.toString actual-error))]
- (println (.replaceFirst message "^Assert failed: " "")))
- false)))
+ (binding [*ns* (create-ns (gensym "koans"))]
+ (refer 'clojure.core)
+ (use 'cascalog.api)
+ (use '[path-to-enlightenment :only [meditations ?= __ ___]])
+ (try (load-file file-path)
+ true
+ (catch Exception e
+ (println)
+ (println "Problem in" file-path)
+ (println "---------------------")
+ (println "Assertion failed!")
+ (let [actual-error (or (.getCause e) e)
+ message (or (.getMessage actual-error)
+ (.toString actual-error))]
+ (println (.replaceFirst message "^Assert failed: " "")))
+ false))))
(defn namaste []
(println "\nYou have achieved clojure enlightenment. Namaste."))

0 comments on commit 389daa5

Please sign in to comment.