diff --git a/resources/koans.clj b/resources/koans.clj index faa46bc4b..90592db64 100644 --- a/resources/koans.clj +++ b/resources/koans.clj @@ -259,11 +259,24 @@ "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 4] + [2 4] + [2 4] + 6]}] ] diff --git a/src/koans/25_threading_macros.clj b/src/koans/25_threading_macros.clj new file mode 100644 index 000000000..21fd58be3 --- /dev/null +++ b/src/koans/25_threading_macros.clj @@ -0,0 +1,70 @@ +(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 [m a b] + (do + (println (str "Other unused arguments: " a " " b)) + (get m :a))) + +(defn function-that-takes-a-coll [a b coll] + (do + (println (str "Other unused arguments: " a " " b)) + (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 funtions we have written ourselves that follow this pattern" + (= __ + (->> a-list-with-maps + (function-that-takes-a-coll "hello" "there") + (into [])))) diff --git a/src/koans/26_transducers.clj b/src/koans/26_transducers.clj new file mode 100644 index 000000000..9772debbd --- /dev/null +++ b/src/koans/26_transducers.clj @@ -0,0 +1,23 @@ +(ns koans.26-transducers + (:require [koan-engine.core :refer :all])) + +(def xfms + (comp (map inc) + (filter even?))) + +(meditations + "Consider that sequence operations can be used as transducers" + (= __ + (transduce xfms conj [1 2 3])) + + "We can do this eagerly" + (= __ + (into [] xfms [1 2 3])) + + "Or lazily" + (= __ + (sequence xfms [1 2 3])) + + "The transduce function can combine mapping and reduction" + (= __ + (transduce xfms + [1 2 3])))