Last active
December 3, 2021 09:16
-
-
Save lildata/e9110d3e84a3d380e15c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (dont cheat) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (ns koans.01-equalities | |
| (:require [koan-engine.core :refer :all])) | |
| (meditations | |
| "We shall contemplate truth by testing reality, via equality" | |
| (= true true) | |
| "To understand reality, we must compare our expectations against reality" | |
| (= 2 (+ 1 1)) | |
| "You can test equality of many things" | |
| (= (+ 3 4) 7 (+ 2 5)) | |
| "Some things may appear different, but be the same" | |
| (= true (= 2 2/1)) | |
| "You cannot generally float to heavens of integers" | |
| (= false (= 2 2.0)) | |
| "But a looser equality is also possible" | |
| (= true (== 2.0 2)) | |
| "Something is not equal to nothing" | |
| (= true (not (= 1 nil))) | |
| "Strings, and keywords, and symbols: oh my!" | |
| (= false (= "hello" :hello 'hello)) | |
| "Make a keyword with your keyboard" | |
| (= :hello (keyword "hello")) | |
| "Symbolism is all around us" | |
| (= 'hello (symbol "hello")) | |
| "When things cannot be equal, they must be different" | |
| (not= :fill-in-the-blank :whatever)) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (ns koans.02-lists | |
| (:require [koan-engine.core :refer :all])) | |
| (meditations | |
| "Lists can be expressed by function or a quoted form" | |
| (= '(1 2 3 4 5) (list 1 2 3 4 5)) | |
| "They are Clojure seqs (sequences), so they allow access to the first" | |
| (= 1 (first '(1 2 3 4 5))) | |
| "As well as the rest" | |
| (= '(2 3 4 5) (rest '(1 2 3 4 5))) | |
| "Count your blessings" | |
| (= 3 (count '(dracula dooku chocula))) | |
| "Before they are gone" | |
| (= 0 (count '())) | |
| "The rest, when nothing is left, is empty" | |
| (= '() (rest '(100))) | |
| "Construction by adding an element to the front is easy" | |
| (= '(:a :b :c :d :e) (cons :a '(:b :c :d :e))) | |
| "Conjoining an element to a list isn't hard either" | |
| (= '(:e :a :b :c :d) (conj '(:a :b :c :d) :e)) | |
| "You can use a list like a stack to get the first element" | |
| (= :a (peek '(:a :b :c :d :e))) | |
| "Or the others" | |
| (= '(:b :c :d :e) (pop '(:a :b :c :d :e))) | |
| "But watch out if you try to pop nothing" | |
| (= "No dice!" (try | |
| (pop '()) | |
| (catch IllegalStateException e | |
| "No dice!"))) | |
| "The rest of nothing isn't so strict" | |
| (= '() (try | |
| (rest '()) | |
| (catch IllegalStateException e | |
| "No dice!")))) | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (ns koans.03-vectors | |
| (:require [koan-engine.core :refer :all])) | |
| (meditations | |
| "You can use vectors in clojure as array-like structures" | |
| (= 1 (count [42])) | |
| "You can create a vector from a list" | |
| (= [1] (vec '(1))) | |
| "Or from some elements" | |
| (= [nil nil] (vector nil nil)) | |
| "But you can populate it with any number of elements at once" | |
| (= [1 2] (vec '(1 2))) | |
| "Conjoining to a vector is different than to a list" | |
| (= [111 222 333] (conj [111 222] 333)) | |
| "You can get the first element of a vector like so" | |
| (= :peanut (first [:peanut :butter :and :jelly])) | |
| "And the last in a similar fashion" | |
| (= :jelly (last [:peanut :butter :and :jelly])) | |
| "Or any index if you wish" | |
| (= :jelly (nth [:peanut :butter :and :jelly] 3)) | |
| "You can also slice a vector" | |
| (= [:butter :and] (subvec [:peanut :butter :and :jelly] 1 3)) | |
| "Equality with collections is in terms of values" | |
| (= (list 1 2 3) (vector 1 2 3))) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (ns koans.04-sets | |
| (:require [koan-engine.core :refer :all] | |
| [clojure.set :as set])) | |
| (meditations | |
| "You can create a set by converting another collection" | |
| (= #{3} (set [3])) | |
| "Counting them is like counting other collections" | |
| (= 3 (count #{1 2 3})) | |
| "Remember that a set is a *mathematical* set" | |
| (= #{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" | |
| (= #{1 2 4 3 5} (set/union #{1 2 3 4} #{2 3 5})) | |
| "And also the intersection" | |
| (= #{2 3} (set/intersection #{1 2 3 4} #{2 3 5})) | |
| "But don't forget about the difference" | |
| (= #{1 4} (set/difference #{1 2 3 4 5} #{2 3 5}))) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (ns koans.05-maps | |
| (:require [koan-engine.core :refer :all])) | |
| (meditations | |
| "Don't get lost when creating a map" | |
| (= {:a 1 :b 2} (hash-map :a 1 :b 2)) | |
| "A value must be supplied for each key" | |
| (= {:a 1} (hash-map :a 1)) | |
| "The size is the number of entries" | |
| (= 2 (count {:a 1 :b 2})) | |
| "You can look up the value for a given key" | |
| (= 2 (get {:a 1 :b 2} :b)) | |
| "Maps can be used as functions to do lookups" | |
| (= 1 ({:a 1 :b 2} :a)) | |
| "And so can keywords" | |
| (= 1 (:a {:a 1 :b 2})) | |
| "But map keys need not be keywords" | |
| (= "Sochi" ({2010 "Vancouver" 2014 "Sochi" 2018 "PyeongChang"} 2014)) | |
| "You may not be able to find an entry for a key" | |
| (= nil (get {:a 1 :b 2} :c)) | |
| "But you can provide your own default" | |
| (= :key-not-found (get {:a 1 :b 2} :c :key-not-found)) | |
| "You can find out if a key is present" | |
| (= true (contains? {:a nil :b nil} :b)) | |
| "Or if it is missing" | |
| (= false (contains? {:a nil :b nil} :c)) | |
| "Maps are immutable, but you can create a new and improved version" | |
| (= {1 "January" 2 "February"} (assoc {1 "January"} 2 "February")) | |
| "You can also create a new version with an entry removed" | |
| (= {1 "January"} (dissoc {1 "January" 2 "February"} 2)) | |
| "Often you will need to get the keys, but the order is undependable" | |
| (= (list 2010 2014 2018) | |
| (sort (keys { 2014 "Sochi" 2018 "PyeongChang" 2010 "Vancouver"}))) | |
| "You can get the values in a similar way" | |
| (= (list "PyeongChang" "Sochi" "Vancouver") | |
| (sort (vals {2010 "Vancouver" 2014 "Sochi" 2018 "PyeongChang"})))) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (ns koans.06-functions | |
| (:require [koan-engine.core :refer :all])) | |
| (defn multiply-by-ten [n] | |
| (* 10 n)) | |
| (defn square [n] (* n n)) | |
| (meditations | |
| "Calling a function is like giving it a hug with parentheses" | |
| (= 81 (square 9)) | |
| "Functions are usually defined before they are used" | |
| (= 20 (multiply-by-ten 2)) | |
| "But they can also be defined inline" | |
| (= 10 ((fn [n] (* 5 n)) 2)) | |
| "Or using an even shorter syntax" | |
| (= 60 (#(* 15 %) 4)) | |
| "Even anonymous functions may take multiple arguments" | |
| (= 15 (#(+ %1 %2 %3) 4 5 6)) | |
| "Arguments can also be skipped" | |
| (= 30 (#(* 15 %2) 1 2)) | |
| "One function can beget another" | |
| (= 9 ((fn [a b] (+ a b)) 4 5)) | |
| "Functions can also take other functions as input" | |
| (= 20 ((fn [f] (f 4 5)) | |
| #(* %1 %2))) | |
| "Higher-order functions take function arguments" | |
| (= 25 (#(% 5) | |
| (fn [n] (* n n)))) | |
| "But they are often better written using the names of functions" | |
| (= 25 (#(% 5) square))) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (ns koans.07-conditionals | |
| (:require [koan-engine.core :refer :all])) | |
| (defn explain-exercise-velocity [exercise-term] | |
| (case exercise-term | |
| :bicycling "pretty fast" | |
| :jogging "not super fast" | |
| :walking "not fast at all" | |
| "is that even exercise?")) | |
| (meditations | |
| "You will face many decisions" | |
| (= :a (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" | |
| (= 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 1) :road-not-taken | |
| (= x 2) :another-road-not-taken | |
| :else :your-road))) | |
| "Or your fate may be sealed" | |
| (= 'doom (if-not (zero? 1) | |
| 'doom | |
| 'more-doom)) | |
| "In case of emergency, go fast" | |
| (= "pretty fast" | |
| (explain-exercise-velocity :bicycling)) | |
| "But admit it when you don't know what to do" | |
| (= "is that even exercise?" | |
| (explain-exercise-velocity :watching-tv))) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (ns koans.08-higher-order-functions | |
| (:require [koan-engine.core :refer :all])) | |
| (meditations | |
| "The map function relates a sequence to another" | |
| (= | |
| [4 8 12] | |
| (map | |
| (fn [x] (* 4 x)) [1 2 3])) | |
| "You may create that mapping" | |
| (= | |
| [1 4 9 16 25] | |
| (map | |
| (fn [x] (* x x)) [1 2 3 4 5])) | |
| "Or use the names of existing functions" | |
| (= [false false true false false] (map nil? [:a :b nil :c :d])) | |
| "A filter can be strong" | |
| (= '() (filter (fn [x] false) '(:anything :goes :here))) | |
| "Or very weak" | |
| (= '(:anything :goes :here) (filter (fn [x] true) '(:anything :goes :here))) | |
| "Or somewhere in between" | |
| (= | |
| [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] (* x 10)) | |
| (filter (fn [x] (< x 4)) [1 2 3 4 5 6 7 8]))) | |
| "Reducing can increase the result" | |
| (= 24 (reduce (fn [a b] (* a b)) [1 2 3 4])) | |
| "You can start somewhere else" | |
| (= | |
| 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 (< (count a) (count b)) b a)) | |
| ["which" "word" "is" "longest"]))) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (ns koans.09-runtime-polymorphism | |
| (:require [koan-engine.core :refer :all])) | |
| (defn hello | |
| ([] "Hello World!") | |
| ([a] (str "Hello, you silly " a ".")) | |
| ([a & more] (str "Hello to this group: " | |
| (apply str | |
| (interpose ", " (cons a more))) | |
| "!"))) | |
| (defmulti diet (fn [x] (:eater x))) | |
| (defmethod diet :herbivore [a] (str (:name a) " eats veggies.")) | |
| (defmethod diet :carnivore [a] (str (:name a) " 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 World!" (hello)) | |
| "With one argument" | |
| (= "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" | |
| (= "Bambi eats veggies." | |
| (diet | |
| {:species "deer" | |
| :name "Bambi" | |
| :age 1 | |
| :eater :herbivore})) | |
| "Animals have different names" | |
| (= "Thumper eats veggies." | |
| (diet {:species "rabbit" :name "Thumper" :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"}))) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (ns koans.10-lazy-sequences | |
| (:require [koan-engine.core :refer :all])) | |
| (meditations | |
| "There are many ways to generate a sequence" | |
| (= '(1 2 3 4) (range 1 5)) | |
| "The range starts at the beginning by default" | |
| (= '(0 1 2 3 4) (range 5)) | |
| "Only take what you need when the sequence is large" | |
| (= [0 1 2 3 4 5 6 7 8 9] | |
| (take 10 (range 100))) | |
| "Or limit results by dropping what you don't need" | |
| (= [95 96 97 98 99] | |
| (drop 95 (range 100))) | |
| "Iteration provides an infinite lazy sequence" | |
| (= '(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19) (take 20 (iterate inc 0))) | |
| "Repetition is key" | |
| (= [:a :a :a :a :a :a :a :a :a :a] | |
| (repeat 10 :a)) | |
| "Iteration can be used for repetition" | |
| (= (repeat 100 :hello) | |
| (take 100 (iterate identity :hello)))) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (ns koans.11-sequence-comprehensions | |
| (:require [koan-engine.core :refer :all])) | |
| (meditations | |
| "Sequence comprehensions can bind each element in turn to a symbol" | |
| (= '(0 1 2 3 4 5) | |
| (for [x (range 6)] | |
| x)) | |
| "They can easily emulate mapping" | |
| (= '(0 1 4 9 16 25) | |
| (map (fn [x] (* x x)) (range 6)) | |
| (for [x (range 6)] (* x x)) | |
| ) | |
| "And also filtering" | |
| (= '(1 3 5 7 9) | |
| (filter odd? (range 10)) | |
| (for [x (range 10) :when (odd? x)] | |
| x)) | |
| "Combinations of these transformations is trivial" | |
| (= '(1 9 25 49 81) | |
| (map (fn [x] (* x x)) | |
| (filter odd? (range 10))) | |
| (for [x (range 10) :when (odd? x)] | |
| (* x x))) | |
| "More complex transformations simply take 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]] | |
| [row column]))) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (ns koans.12-creating-functions | |
| (:require [koan-engine.core :refer :all])) | |
| (defn square [x] (* x x)) | |
| (meditations | |
| "One may know what they seek by knowing what they do not seek" | |
| (= [true false true] (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? (complement nil?)] | |
| (filter not-nil? [nil :wheat nil "wheat" nil 'wheat nil]))) | |
| "Partial functions allow procrastination" | |
| (= 20 (let [multiply-by-5 (partial * 5)] | |
| (multiply-by-5 4))) | |
| "Don't forget: first things first" | |
| (= [:a :b :c :d] | |
| (let [ab-adder (partial concat [:a :b])] | |
| (ab-adder [:c :d]))) | |
| "Functions can join forces as one 'composed' function" | |
| (= 25 (let [inc-and-square (comp square inc)] | |
| (inc-and-square 4))) | |
| "Have a go on a double dec-er" | |
| (= 8 (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 (comp dec square)] | |
| (square-and-dec 10)))) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (ns koans.13-recursion | |
| (:require [koan-engine.core :refer :all])) | |
| (defn is-even? [n] | |
| (if (= n 0) | |
| true | |
| (not (is-even? (dec n))))) | |
| (defn is-even-bigint? [n] | |
| (loop [n n | |
| acc true] | |
| (if (= n 0) | |
| acc | |
| (recur (dec n) (not acc))))) | |
| (defn recursive-reverse [coll] | |
| (loop [in coll out '()] | |
| (if(empty? in) | |
| out | |
| (recur (rest in) (cons (first in) out))))) | |
| (defn factorial [n] | |
| (loop [n n acc 1] | |
| (if (= 0 n) | |
| acc | |
| (recur (dec n) (* n acc))))) | |
| (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 it becomes 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 100003N))) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (ns koans.14-destructuring | |
| (:require [koan-engine.core :refer :all])) | |
| (def test-address | |
| {:street-address "123 Test Lane" | |
| :city "Testerville" | |
| :state "TX"}) | |
| (meditations | |
| "Destructuring is an arbiter: it breaks up arguments" | |
| (= ":bar:foo" ((fn [[a b]] (str b a)) | |
| [:foo :bar])) | |
| "Whether in function definitions" | |
| (= (str "An Oxford comma list of apples, " | |
| "oranges, " | |
| "and pears.") | |
| ((fn [[a b c]] (str "An Oxford comma list of " a ", " b ", and " c ".")) | |
| ["apples" "oranges" "pears"])) | |
| "Or in let expressions" | |
| (= "Rich Hickey aka The Clojurer aka Go Time aka Lambda Guru" | |
| (let [[first-name last-name & aliases] | |
| (list "Rich" "Hickey" "The Clojurer" "Go Time" "Lambda Guru")] | |
| (str first-name " " last-name " aka " (apply str (interpose " aka " aliases))))) | |
| "You can regain the full argument if you like arguing" | |
| (= {:original-parts ["Stephen" "Hawking"] :named-parts {:first "Stephen" :last "Hawking"}} | |
| (let [[first-name last-name :as full-name] ["Stephen" "Hawking"]] | |
| {:original-parts [first-name last-name] :named-parts {:first first-name :last last-name}})) | |
| "Break up maps by key" | |
| (= "123 Test Lane, Testerville, TX" | |
| (let [{street-address :street-address, city :city, state :state} test-address] | |
| (str street-address ", " city ", " state))) | |
| "Or more succinctly" | |
| (= "123 Test Lane, Testerville, TX" | |
| (let [{:keys [street-address city state]} test-address] | |
| (str street-address ", " city ", " state))) | |
| "All together now!" | |
| (= "Test Testerson, 123 Test Lane, Testerville, TX" | |
| ((fn[[first-name last-name] {:keys [street-address city state]}] | |
| (str first-name " " last-name ", " street-address ", " city ", " state )) ["Test" "Testerson"] test-address))) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (ns koans.15-refs | |
| (:require [koan-engine.core :refer :all])) | |
| (def the-world (ref "hello")) | |
| (def bizarro-world (ref {})) | |
| (meditations | |
| "In the beginning, there was a word" | |
| (= "hello" (deref the-world)) | |
| "You can get the word more succinctly, but it's the same" | |
| (= "hello" @the-world) | |
| "You can be the change you wish to see in the world." | |
| (= "better" | |
| (do | |
| (dosync | |
| (ref-set the-world "better")) @the-world)) | |
| "Alter where you need not replace" | |
| (= "better!!!" (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 (dosync (ref-set the-world 0)) @the-world)) | |
| "Functions passed to alter may depend on the data in the ref" | |
| (= 20 (do | |
| (dosync (alter the-world + 20)))) | |
| "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") | |
| [(:jerry @the-world) (:jerry @bizarro-world)])))) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (ns koans.16-atoms | |
| (:require [koan-engine.core :refer :all])) | |
| (def atomic-clock (atom 0)) | |
| (meditations | |
| "Atoms are like refs" | |
| (= 0 @atomic-clock) | |
| "You can change at the swap meet" | |
| (= 1 (do | |
| (swap! atomic-clock inc) | |
| @atomic-clock)) | |
| "Keep taxes out of this: swapping requires no transaction" | |
| (= 5 (do | |
| (swap! atomic-clock + 4) | |
| @atomic-clock)) | |
| "Any number of arguments might happen during a swap" | |
| (= 20 (do | |
| (swap! atomic-clock + 1 2 3 4 5) | |
| @atomic-clock)) | |
| "Atomic atoms are atomic" | |
| (= 20 (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 20 :fin) | |
| @atomic-clock))) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (ns koans.17-macros | |
| (:require [koan-engine.core :refer :all])) | |
| (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! | |
| ~(first form) | |
| ~(nth form 2))) | |
| (defmacro r-infix [form] | |
| (cond (not (seq? form)) | |
| form ;... | |
| (= 1 (count form)) | |
| `(r-infix ~(first form)) | |
| :else | |
| (let [operator (second form) | |
| first-arg (first form) | |
| others (rest (rest form))] ; ... | |
| `(~operator | |
| (r-infix ~first-arg) | |
| (r-infix ~others))))) | |
| (meditations | |
| "Macros are like functions created at compile time" | |
| (= "Hello, Macros!" (hello "Macros!")) | |
| "I can haz infix?" | |
| (= 10 (infix (9 + 1))) | |
| "Remember, these are nothing but code transformations" | |
| (= '(+ 9 1) (macroexpand '(infix (9 + 1)))) | |
| "You can do better than that - hand crafting FTW!" | |
| (= '(* 10 2) (macroexpand '(infix-better (10 * 2)))) | |
| "Things don't always work as you would like them to... " | |
| (= '(+ 10 (2 * 3)) (macroexpand '(infix-better ( 10 + (2 * 3))))) | |
| "Really, you don't understand recursion until you understand recursion" | |
| (= 36 (r-infix (10 + (2 * 3) + (4 * 5))))) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (ns koans.18-datatypes | |
| (:require [koan-engine.core :refer :all])) | |
| (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] | |
| (print (str "You're really the " | |
| category ", " | |
| recipient | |
| "... sorry.")))) | |
| (meditations | |
| "Holding records is meaningful only when the record is worthy of you" | |
| (= "peace" (.prize (Nobel. "peace"))) | |
| "Types are quite similar" | |
| (= "literature" (.prize (Pulitzer. "literature"))) | |
| "Records may be treated like maps" | |
| (= "physics" (:prize (Nobel. "physics"))) | |
| "While types may not" | |
| (= nil (:prize (Pulitzer. "poetry"))) | |
| "Further study reveals why" | |
| (= '(true false) | |
| (map map? [(Nobel. "chemistry") | |
| (Pulitzer. "music")])) | |
| "Either sort of datatype can define methods in a protocol" | |
| (= (str "Congratulations on your " "Best Picture" " Oscar, " "Evil Alien Conquerors" "!") | |
| (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")))) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (ns koans.19-java-interop | |
| (:require [koan-engine.core :refer :all])) | |
| (meditations | |
| "You may have done more with Java than you know" | |
| (= java.lang.String (class "warfare")) ; hint: try typing (javadoc "warfare") in the REPL | |
| "The dot signifies easy and direct Java interoperation" | |
| (= "SELECT * FROM" (.toUpperCase "select * from")) | |
| "But instance method calls are very different from normal functions" | |
| (= ["SELECT" "FROM" "WHERE"] (map #(.toUpperCase %) ["select" "from" "where"])) ; you need a real function... | |
| "Constructing might be harder than breaking" | |
| (= 10 (let [latch (java.util.concurrent.CountDownLatch. 10)] | |
| (.getCount latch))) | |
| "Static methods are slashing prices!" | |
| (== 1024 (Math/pow 2 10))) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (ns koans.20-partition | |
| (:require [koan-engine.core :refer :all])) | |
| (meditations | |
| "To split a collection you can use the partition function" | |
| (= '((0 1) (2 3)) (partition 2 (range 4))) | |
| "But watch out if there are not enough elements to form n sequences" | |
| (= '([:a :b :c]) (partition 3 [:a :b :c :d :e])) ;they just disapear, strange... | |
| "You can use partition-all to also get partitions with less than n elements" | |
| (= '((0 1 2) (3 4)) (partition-all 3 (range 5))) | |
| "If you need to, you can start each sequence with an offset" | |
| (= '((0 1 2) (5 6 7) (10 11 12)) (partition 3 5 (range 13))) | |
| "Consider padding the last sequence with some default values..." | |
| (= '((0 1 2) (3 4 5) (6 :hello)) (partition 3 3 [:hello] (range 7))) | |
| "... but notice that they will only pad up to the given sequence length" | |
| (= '((0 1 2) (3 4 5) (6 :these :are)) (partition 3 3 [:these :are "my" "words"] (range 7)))) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (ns koans.21-group-by | |
| (:require [koan-engine.core :refer :all])) | |
| (defn get-odds-and-evens [coll] | |
| (let [{odds true evens false} (group-by odd? coll)] | |
| [odds evens])) | |
| (meditations | |
| "To categorize a collection by some function, use group-by." | |
| (= {5 ["hello" "world"] 3 ["foo" "bar"]} (group-by count ["hello" "world" "foo" "bar"])) | |
| "You can simulate filter + remove in one pass" | |
| (= (get-odds-and-evens [1 2 3 4 5]) | |
| ((juxt filter remove) odd? [1 2 3 4 5]) | |
| [[1 3 5] [2 4]]) | |
| "You can also group by a primary key" | |
| (= { 1 [{:id 1 :name "Bob"} {:id 1 :last-name "Smith"}] | |
| 2 [{:id 2 :name "Jennifer"}]} | |
| (group-by :id [{:id 1 :name "Bob"} | |
| {:id 2 :name "Jennifer"} | |
| {:id 1 :last-name "Smith"} ])) | |
| "But be careful when you group by a non-required key" | |
| (= {"Bob" [{:name "Bob" :id 1}] | |
| "Jennifer" [{:name "Jennifer" :id 2}] | |
| nil [{:last-name "Smith" :id 1}]} | |
| (group-by :name [{:id 1 :name "Bob"} | |
| {:id 2 :name "Jennifer"} | |
| {:id 1 :last-name "Smith"}])) | |
| "The true power of group-by comes with custom functions" | |
| (= {:naughty-list [{:name "Jimmy" :bad true}{:name "Joe" :bad true}] | |
| :nice-list [{:name "Jane" :bad false}] | |
| } | |
| (group-by #(if (:bad %) :naughty-list :nice-list) | |
| [{:name "Jimmy" :bad true} | |
| {:name "Jane" :bad false} | |
| {:name "Joe" :bad true}]))) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (ns koans.22-meta | |
| (:require [koan-engine.core :refer :all])) | |
| (def giants | |
| (with-meta 'Giants | |
| {:league "National League"})) | |
| (meditations | |
| "Some objects can be tagged using the with-meta function" | |
| (= {:league "National League"} (meta giants)) | |
| "Or more succintly with a reader macro" | |
| (= {:division "West"} (meta '^{:division "West"} Giants)) | |
| "While others can't" | |
| (= "This doesn't implement the IObj interface" | |
| (try | |
| (with-meta | |
| 2 | |
| {:prime true}) | |
| (catch ClassCastException e | |
| "This doesn't implement the IObj interface"))) | |
| "Notice when metadata carries over" | |
| (= {:foo :bar} | |
| (meta (merge '^{:foo :bar} {:a 1 :b 2} | |
| {:b 3 :c 4}))) | |
| "And when it doesn't" | |
| (= nil (meta (merge {:a 1 :b 2} | |
| '^{:foo :bar} {:b 3 :c 4}))) | |
| "Metadata can be used as a type hint to avoid reflection during runtime" | |
| (= \C (#(.charAt ^String % 0) "Cast me")) | |
| "You can directly update an object's metadata" | |
| (= 8 (let [giants (with-meta 'Giants {:world-series-titles (atom 7)})] | |
| (swap! (:world-series-titles (meta giants)) inc) | |
| @(:world-series-titles (meta giants)))) | |
| "You can also create a new object from another object with metadata" | |
| (= {:league "National League" :park "AT&T Park"} | |
| (meta (vary-meta giants | |
| assoc :park "AT&T Park"))) | |
| "But it won't affect behavior like equality" | |
| (= giants (vary-meta giants dissoc :league)) | |
| "Or the object's printed representation" | |
| (= "Giants" (pr-str (vary-meta giants dissoc :league)))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment