Compare commits

..

13 commits

Author SHA1 Message Date
Sam Baumann
8d2b6ecc98 Switch 'AT&T Park' to 'Oracle Park' on answer sheet 2024-05-28 15:23:52 -05:00
Sergey Makarichev
76b279a8a8 Fix some typos and style non-uniformities 2023-01-04 15:20:56 -06:00
Ivan Bilous
3ddfa8c241 Fix grammar 2022-09-17 10:58:07 -05:00
William Vaughn
9ed29b7922 change Giants ballpark from AT&T to Oracle 2022-01-29 16:39:10 -06:00
Nick Reilingh
a9c22921a5 27_multimethods.clj - fixed typo?
The word "do" seems to be missing in the final koan.
2020-07-08 10:10:08 -05:00
neta-kedem
d749795c31 fixing typo
missing c in the word function
2019-12-02 13:48:27 -06:00
neta-kedem
040070bbed text styling
"A multimethod takes one or more arguments" sound better than previous version
2019-12-02 13:48:01 -06:00
Alex Lynham
eb73f39c9e Add some simple examples for multimethods 2019-10-28 16:37:33 -05:00
Spenser Truex
9c115996f9 Fixed whitespace: trailing and indent. 2019-10-28 16:35:08 -05:00
Alex Lynham
3afe01adc7 Address changes to PR adding threading forms 2019-09-23 10:50:43 -05:00
Alex Lynham
ba141d0fc2 Add some examples for threading macros and a couple of simple transducer koans 2019-09-23 10:50:43 -05:00
Jonathan Chen
9481906390 docs: fix spelling (#142) 2019-06-10 10:10:03 -05:00
Colin Jones
3cc7b91c23
Back to snapshot 2018-12-31 09:39:05 -06:00
15 changed files with 179 additions and 20 deletions

View file

@ -152,7 +152,7 @@ to add to existing koans. So write some fun exercises, add your answers to
Please follow the guidelines in Please follow the guidelines in
http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html for http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html for
commmit messages, and put your code in a feature branch (not master) before commit messages, and put your code in a feature branch (not master) before
making the pull request. This makes patches easier to review. making the pull request. This makes patches easier to review.
Feel free to contact me (Colin Jones / trptcolin) on Github or elsewhere if you Feel free to contact me (Colin Jones / trptcolin) on Github or elsewhere if you

View file

@ -1,4 +1,4 @@
(defproject clojure-koans "0.5.1" (defproject clojure-koans "0.5.2-SNAPSHOT"
:description "The Clojure koans." :description "The Clojure koans."
:dependencies [[org.clojure/clojure "1.10.0"] :dependencies [[org.clojure/clojure "1.10.0"]
[koan-engine "0.2.5"]] [koan-engine "0.2.5"]]

View file

@ -254,16 +254,35 @@
nil nil
\C \C
inc inc
:park "AT&T Park" :park "Oracle Park"
'Giants 'Giants
"Giants"]}] "Giants"]}]
["24_macros" {"__" [~(first form) ["24_macros" {"__" [~(first form)
~(nth form 2) ~(nth form 2)
form form
(drop 2 form) (drop 2 form)
"Hello, Macros!" "Hello, Macros!"
10 10
'(+ 9 1)]}] '(+ 9 1)]}]
["25_threading_macros" {"__" [{:a 1}
"Hello world, and moon, and stars"
"String with a trailing space"
6
1
[2 3 4]
12
[1 2 3]]}]
["26_transducers" {"__" ['(2 3 4)
[2 4]
[2 4]
[2 4]
6]}]
["27_multimethods" {"__" ["Hello, World!"
"Hello there"
1
6]}]
] ]

View file

@ -39,7 +39,7 @@
"Maybe you want to find the index of the first occurrence of a substring" "Maybe you want to find the index of the first occurrence of a substring"
(= 0 (string/index-of "hello world" __)) (= 0 (string/index-of "hello world" __))
"Or maybe the last index of the same" "Or maybe the last index of the same substring"
(= __ (string/last-index-of "hello world, hello" "hello")) (= __ (string/last-index-of "hello world, hello" "hello"))
"But when something doesn't exist, nothing is found" "But when something doesn't exist, nothing is found"

View file

@ -12,7 +12,7 @@
"Remember that a set is a *mathematical* set" "Remember that a set is a *mathematical* set"
(= __ (set '(1 1 2 2 3 3 4 4 5 5))) (= __ (set '(1 1 2 2 3 3 4 4 5 5)))
"You can ask clojure for the union of two sets" "You can ask Clojure for the union of two sets"
(= __ (set/union #{1 2 3 4} #{2 3 5})) (= __ (set/union #{1 2 3 4} #{2 3 5}))
"And also the intersection" "And also the intersection"

View file

@ -20,7 +20,7 @@
(for [x __ :when (odd? x)] (for [x __ :when (odd? x)]
x)) x))
"Combinations of these transformations is trivial" "Combinations of these transformations are trivial"
(= '(1 9 25 49 81) (= '(1 9 25 49 81)
(map (fn [x] (* x x)) (map (fn [x] (* x x))
(filter odd? (range 10))) (filter odd? (range 10)))

View file

@ -35,10 +35,10 @@
"Yet it becomes more difficult the more steps you take" "Yet it becomes more difficult the more steps you take"
(= '(6 5 4 3 2) (recursive-reverse [2 3 4 5 6])) (= '(6 5 4 3 2) (recursive-reverse [2 3 4 5 6]))
"Simple things may appear simple." "Simple things may appear simple"
(= 1 (factorial 1)) (= 1 (factorial 1))
"They may require other simple steps." "They may require other simple steps"
(= 2 (factorial 2)) (= 2 (factorial 2))
"Sometimes a slightly bigger step is necessary" "Sometimes a slightly bigger step is necessary"

View file

@ -29,7 +29,7 @@
(let [[first-name last-name :as full-name] ["Stephen" "Hawking"]] (let [[first-name last-name :as full-name] ["Stephen" "Hawking"]]
__)) __))
"Break up maps by key" "Break up maps by keys"
(= "123 Test Lane, Testerville, TX" (= "123 Test Lane, Testerville, TX"
(let [{street-address :street-address, city :city, state :state} test-address] (let [{street-address :street-address, city :city, state :state} test-address]
__)) __))

View file

@ -14,8 +14,8 @@
"If you need to, you can start each sequence with an offset" "If you need to, you can start each sequence with an offset"
(= '((0 1 2) (5 6 7) (10 11 12)) (partition 3 __ (range 13))) (= '((0 1 2) (5 6 7) (10 11 12)) (partition 3 __ (range 13)))
"Consider padding the last sequence with some default values..." "Consider padding the last sequence with some default values"
(= '((0 1 2) (3 4 5) (6 :hello)) (partition 3 3 [__] (range 7))) (= '((0 1 2) (3 4 5) (6 :hello)) (partition 3 3 [__] (range 7)))
"... but notice that they will only pad up to the given sequence length" "But notice that they will only pad up to the given sequence length"
(= '((0 1 2) (3 4 5) __) (partition 3 3 [:these :are "my" "words"] (range 7)))) (= '((0 1 2) (3 4 5) __) (partition 3 3 [:these :are "my" "words"] (range 7))))

View file

@ -6,7 +6,7 @@
[odds evens])) [odds evens]))
(meditations (meditations
"To categorize a collection by some function, use group-by." "To categorize a collection by some function, use group-by"
(= __ (group-by count ["hello" "world" "foo" "bar"])) (= __ (group-by count ["hello" "world" "foo" "bar"]))
"You can simulate filter + remove in one pass" "You can simulate filter + remove in one pass"

View file

@ -40,7 +40,7 @@
@(:world-series-titles (meta giants)))) @(:world-series-titles (meta giants))))
"You can also create a new object from another object with metadata" "You can also create a new object from another object with metadata"
(= {:league "National League" :park "AT&T Park"} (= {:league "National League" :park "Oracle Park"}
(meta (vary-meta giants (meta (vary-meta giants
assoc __ __))) assoc __ __)))

View file

@ -38,7 +38,7 @@
"You can do better than that - hand crafting FTW!" "You can do better than that - hand crafting FTW!"
(= '(* 10 2) (macroexpand '(infix-concise (10 * 2)))) (= '(* 10 2) (macroexpand '(infix-concise (10 * 2))))
"Things don't always work as you would like them to... " "Things don't always work as you would like them to"
(= '(+ 10 (2 * 3)) (macroexpand '(infix-concise (10 + (2 * 3))))) (= '(+ 10 (2 * 3)) (macroexpand '(infix-concise (10 + (2 * 3)))))
"Really, you don't understand recursion until you understand recursion" "Really, you don't understand recursion until you understand recursion"

View file

@ -0,0 +1,66 @@
(ns koans.25-threading-macros
(:require [koan-engine.core :refer :all]))
(def a-list
'(1 2 3 4 5))
(def a-list-with-maps
'({:a 1} {:a 2} {:a 3}))
(defn function-that-takes-a-map [map a b]
(get map :a))
(defn function-that-takes-a-coll [a b coll]
(map :a coll))
(meditations
"We can use thread first for more readable sequential operations"
(= __
(-> {}
(assoc :a 1)))
"Consider also the case of strings"
(= __
(-> "Hello world"
(str ", and moon")
(str ", and stars")))
"When a function has no arguments to partially apply, just reference it"
(= __
(-> "String with a trailing space "
clojure.string/trim))
"Most operations that take a scalar value as an argument can be threaded-first"
(= __
(-> {}
(assoc :a 1)
(assoc :b 2)
(assoc :c {:d 4
:e 5})
(update-in [:c :e] inc)
(get-in [:c :e])))
"We can use functions we have written ourselves that follow this pattern"
(= __
(-> {}
(assoc :a 1)
(function-that-takes-a-map "hello" "there")))
"We can also thread last using ->>"
(= __
(->> [1 2 3]
(map inc)))
"Most operations that take a collection can be threaded-last"
(= __
(->> a-list
(map inc)
(filter even?)
(into [])
(reduce +)))
"We can use functions we have written ourselves that follow this pattern"
(= __
(->> a-list-with-maps
(function-that-takes-a-coll "hello" "there")
(into []))))

View file

@ -0,0 +1,30 @@
(ns koans.26-transducers
(:require [koan-engine.core :refer :all]))
(def example-transducer
(map inc))
(def transforms
(comp (map inc)
(filter even?)))
(meditations
"A sequence operation with only one argument often returns a transducer"
(= __
(sequence example-transducer [1 2 3]))
"Consider that sequence operations can be composed as transducers"
(= __
(transduce transforms conj [1 2 3]))
"We can do this eagerly"
(= __
(into [] transforms [1 2 3]))
"Or lazily"
(= __
(sequence transforms [1 2 3]))
"The transduce function can combine mapping and reduction"
(= __
(transduce transforms + [1 2 3])))

View file

@ -0,0 +1,44 @@
(ns koans.27-multimethods
(:require [koan-engine.core :refer :all]))
(defmulti multimethod-without-args
(fn [keyword-arg] keyword-arg))
(defmethod multimethod-without-args :first [_]
(str "Hello, World!"))
(defmethod multimethod-without-args :second [_]
(str "Hello there"))
(defmulti multimethod-with-args
(fn [opt-one opt-two] opt-one))
(defmethod multimethod-with-args :path-one [_ opts]
(:first-opt opts))
(defmethod multimethod-with-args :path-two [_ opts]
(let [numbers (:second-opt opts)]
(->> numbers
(map inc)
(reduce +))))
(defmethod multimethod-with-args :path-three [_])
(meditations
"A multimethod takes one or more arguments to dispatch on"
(= __
(multimethod-without-args :first))
"Though it can be ignored and represented by _ in defmethods"
(= __
(multimethod-without-args :second))
"Alternatively, we can use the arguments in defmethods"
(= __
(multimethod-with-args :path-one {:first-opt 1
:second-opt 2}))
"This allows us to do something different in each method implementation"
(= __
(multimethod-with-args :path-two {:first-opt 1
:second-opt [0 1 2]})))