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
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.
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."
:dependencies [[org.clojure/clojure "1.10.0"]
[koan-engine "0.2.5"]]

View file

@ -254,16 +254,35 @@
nil
\C
inc
:park "AT&T Park"
:park "Oracle Park"
'Giants
"Giants"]}]
["24_macros" {"__" [~(first form)
~(nth form 2)
form
(drop 2 form)
"Hello, Macros!"
10
'(+ 9 1)]}]
~(nth form 2)
form
(drop 2 form)
"Hello, Macros!"
10
'(+ 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"
(= 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"))
"But when something doesn't exist, nothing is found"

View file

@ -12,7 +12,7 @@
"Remember that a set is a *mathematical* set"
(= __ (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}))
"And also the intersection"

View file

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

View file

@ -35,10 +35,10 @@
"Yet it becomes more difficult the more steps you take"
(= '(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))
"They may require other simple steps."
"They may require other simple steps"
(= 2 (factorial 2))
"Sometimes a slightly bigger step is necessary"

View file

@ -29,7 +29,7 @@
(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"
(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"
(= '((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)))
"... 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))))

View file

@ -6,7 +6,7 @@
[odds evens]))
(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"]))
"You can simulate filter + remove in one pass"

View file

@ -40,7 +40,7 @@
@(:world-series-titles (meta giants))))
"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
assoc __ __)))

View file

@ -38,7 +38,7 @@
"You can do better than that - hand crafting FTW!"
(= '(* 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)))))
"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]})))