Friday, September 30, 2016

Kata: Variation on Cellular Automata, animating automaton evolution using re-frame

In the last Clojure Developers Barcelona meetup, we started to use re-frame to animate in the browser the code to evolve cellular automata that we wrote some weeks ago.

We managed to make a rough version but we didn't have time to test it and make it nice.

When I got home I redid the exercise from scratch using a mix of TDD and REPL Driven Development.

First, I coded a couple of evolution rules. These are their tests:

(ns cellular-animation.rules-test
(:require
[cljs.test :refer-macros [deftest testing is]]
[cellular-animation.rules :as rules]))
(deftest rules-tests
(testing "rule 90"
;+-----------------------------------------------------------------+
;| Neighborhood | 111 | 110 | 101 | 100 | 011 | 010 | 001 | 000 |
;+-----------------------------------------------------------------+
;| New Center Cell | 0 | 1 | 0 | 1 | 1 | 0 | 1 | 0 |
;+-----------------------------------------------------------------+
(is (= (rules/rule-90 [1 1 1]) 0))
(is (= (rules/rule-90 [1 1 0]) 1))
(is (= (rules/rule-90 [1 0 1]) 0))
(is (= (rules/rule-90 [1 0 0]) 1))
(is (= (rules/rule-90 [0 1 1]) 1))
(is (= (rules/rule-90 [0 1 0]) 0))
(is (= (rules/rule-90 [0 0 1]) 1))
(is (= (rules/rule-90 [0 0 0]) 0)))
(testing "rule 30"
;+-----------------------------------------------------------------+
;| Neighborhood | 111 | 110 | 101 | 100 | 011 | 010 | 001 | 000 |
;+-----------------------------------------------------------------+
;| New Center Cell | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 0 |
;+-----------------------------------------------------------------+
(is (= (rules/rule-30 [1 1 1]) 0))
(is (= (rules/rule-30 [1 1 0]) 0))
(is (= (rules/rule-30 [1 0 1]) 0))
(is (= (rules/rule-30 [1 0 0]) 1))
(is (= (rules/rule-30 [0 1 1]) 1))
(is (= (rules/rule-30 [0 1 0]) 1))
(is (= (rules/rule-30 [0 0 1]) 1))
(is (= (rules/rule-30 [0 0 0]) 0))))
and this is their code:

(ns cellular-animation.rules)
(def rule-90
{[1 1 1] 0
[1 1 0] 1
[1 0 1] 0
[1 0 0] 1
[0 1 1] 1
[0 1 0] 0
[0 0 1] 1
[0 0 0] 0})
(def rule-30
{[1 1 1] 0
[1 1 0] 0
[1 0 1] 0
[1 0 0] 1
[0 1 1] 1
[0 1 0] 1
[0 0 1] 1
[0 0 0] 0})
Next, I coded the cellular automata evolution, these are its tests:

(ns cellular-animation.evolution-test
(:require
[cljs.test :refer-macros [deftest testing is]]
[cellular-animation.evolution :as evolution]
[cellular-animation.rules :as rules]))
(deftest cellular-automaton-evolution
(testing "evolution from an initial state"
(is (= (evolution/evolve rules/rule-90 [[1]])
[[0 1 0]
[1 0 1]]))
(is (= (evolution/evolve rules/rule-90 [[0 1 0] [1 0 1]])
[[0 0 1 0 0]
[0 1 0 1 0]
[1 0 0 0 1]]))))
and the resulting code:

(ns cellular-animation.evolution)
(defn- extract-neighborhoods [state]
(partition 3 1 (repeat 0) (cons 0 state)))
(defn- evolve-once [rule state]
(mapv rule (extract-neighborhoods state)))
(defn- pad-with-zeroes [state]
(vec (cons 0 (conj state 0))))
(defn- next-state [rule state]
(->> state
pad-with-zeroes
(evolve-once rule)))
(defn evolve [rule states]
(->> (last states)
(next-state rule)
(conj (mapv pad-with-zeroes states))
vec))
Once I had the evolution working, I started to work on the view, using Figwheel and a hard-coded list of cellular automaton states on the db. This way I focused only on rendering the list of cellular automaton states.

With that working, I played on the REPL to create a subscriber that reacted to changes on the cellular automaton states making the view render.

This is the resulting code of the view:

(ns cellular-animation.views
(:require
[re-frame.core :as re-frame]))
(def ^:private cell-representations
{0 "\u00A0" 1 "*"})
(defn- render-state [state-index cell-index cell-state]
(with-meta
[:span.cell (cell-representations cell-state)]
{:key (str "cell-state-" state-index "-cell-" cell-index)}))
(defn- render-states [state-index state]
(with-meta
[:div
(map-indexed (partial render-state state-index) state)]
{:key (str "state-" state-index)}))
(defn- automaton-component []
(let [automaton-states (re-frame/subscribe [:automaton-states])]
(fn []
[:div
{:on-click #(re-frame/dispatch [:evolution-started-or-stopped])}
(map-indexed render-states @automaton-states)])))
(defn main-panel []
[automaton-component])
the code of the subscriber:

(ns cellular-animation.subs
(:require-macros
[reagent.ratom :refer [reaction]])
(:require
[re-frame.core :as re-frame]))
(re-frame/reg-sub
:automaton-states
(fn [db]
(:automaton-states db)))
and the default db:

(ns cellular-animation.db
(:require
[cellular-animation.rules :as rules]))
(def default-db
{:automaton-states [[1]]
:rule rules/rule-90
:evolving false})
Then, I used TDD to write the event handlers.

The use of effects keeps re-frame handlers pure. They allow us to avoid making side effects. We just have to describe as data the computation that will be made instead of doing it. re-frame takes care of that part.

These are the handlers tests:

(ns cellular-animation.handlers-test
(:require
[cljs.test :refer-macros [deftest testing is]]
[cellular-animation.handlers :as handlers]
[cellular-animation.rules :as rules]))
(deftest evolve-handler-test
(testing "when the automaton is evolving it calls itself after changing its state"
(let [initial-states [[1]]
expected-states [[0 1 0] [1 0 1]]
db {:automaton-states initial-states :rule rules/rule-90 :evolving true}]
(is (= (handlers/evolve-handler {:db db} [])
{:db (merge db {:automaton-states expected-states})
:dispatch-later [{:ms 100 :dispatch [:evolve]}]}))))
(testing "when the automaton is not evolving it does not change its state"
(let [db {:automaton-states :not-used-initial-states :rule :not-used-rule :evolving false}]
(is (= (handlers/evolve-handler {:db db} []) {:db db})))))
(deftest start-stop-evolution-test
(testing "when the automaton is evolving it stops the evolution"
(let [db {:evolving true}]
(is (= (handlers/start-stop-evolution {:db db} [])
{:db (assoc db :evolving false)
:dispatch [:evolve]}))))
(testing "when the automaton is not evolving it starts the evolution"
(let [db {:evolving false}]
(is (= (handlers/start-stop-evolution {:db db} [])
{:db (assoc db :evolving true)
:dispatch [:evolve]})))))
these are the handlers:

(ns cellular-animation.handlers
(:require
[cellular-animation.evolution :as evolution]))
(defn evolve-handler [{:keys [db]} _]
(if (:evolving db)
{:db (update db :automaton-states
(partial evolution/evolve (:rule db)))
:dispatch-later [{:ms 100 :dispatch [:evolve]}]}
{:db db}))
(defn start-stop-evolution [{:keys [db]} _]
{:db (update db :evolving not)
:dispatch [:evolve]})
Notice, how in order to dispatch to another handler (a side effect) we just have to add a key-value pair to the map of effects returned by the handler. In this case, I used the :dispatch and :dispatch-later effects which are part of re-frame's built-in effects. You can also create and register your own effects (I will talk about it in some future post).

To see the whole picture this is the code that registers the handlers:

(ns cellular-animation.register-handlers
(:require
[re-frame.core :as re-frame]
[cellular-animation.db :as db]
[cellular-animation.handlers :as handlers]))
(re-frame/reg-event-db
:initialize-db
(fn [_ _]
db/default-db))
(re-frame/reg-event-fx
:evolution-started-or-stopped handlers/start-stop-evolution)
(re-frame/reg-event-fx
:evolve handlers/evolve-handler)
I think that effects and coeffects (I'll talk about them in a future post) are just great!

They make testing handlers logic very easy (since handlers keep being pure functions) and avoid having to use test doubles.

Finally, everything is put together in the core namespace:

(ns cellular-animation.core
(:require
[reagent.core :as reagent]
[re-frame.core :as re-frame]
[devtools.core :as devtools]
[cellular-animation.register-handlers]
[cellular-animation.subs]
[cellular-animation.views :as views]
[cellular-animation.config :as config]))
(defn dev-setup []
(when config/debug?
(enable-console-print!)
(println "dev mode")
(devtools/install!)))
(defn mount-root []
(reagent/render [views/main-panel]
(.getElementById js/document "app")))
(defn ^:export init []
(re-frame/dispatch-sync [:initialize-db])
(dev-setup)
(mount-root))
You can see the cellular automaton evolving in this video (I used garden library to add some CSS to make it look nicer):

You can find the code on this GitHub repository.

In this post I've tried to, somehow, describe the process I followed to write this code, but the previous gists just reflect the final version of the code. If you want to follow how the code evolved, have a look to all the commits on Github.

I really love using ClojureScript and re-frame with Figwheel.

Wednesday, September 28, 2016

Kata: Variation on Lights Out, a bit of FRP using reagi library

To finish with the series of exercises we've been doing lately around the Lights Out kata, I decided to use reagi library to raise the level of abstraction of the communications between the Lights and the LightsGateway components.

reagi is an FRP library for Clojure and ClojureScript which is built on top of core.async. I discovered it while reading Leonardo Borges' wonderful Clojure Reactive Programming book.

I started from the code of the version using the component library I posted recently about and introduced reagi. Let's see the code.

Let's start with the lights-gateway name space:

(ns kata-lights-out.lights-gateway
(:require
[cljs-http.client :as http]
[com.stuartsierra.component :as component]
[reagi.core :as reagi]
[cljs.core.async :as async])
(:require-macros
[cljs.core.async.macros :refer [go]]))
(defn- extract-lights [response]
(->> response
:body
(.parse js/JSON)
.-lights
js->clj))
(defn- post [lights-stream uri params]
(go
(when-let [response (async/<!
(http/post uri
{:with-credentials? false
:form-params params}))]
(reagi/deliver lights-stream
(extract-lights response)))))
(defprotocol LightsGateway
(reset-lights! [this m n])
(flip-light! [this pos]))
(defrecord ApiLightsGateway [config]
component/Lifecycle
(start [this]
(println ";; Starting ApiLightsGateway component")
(assoc this :lights-stream (reagi/events)))
(stop [this]
(println ";; Stopping ApiLightsGateway component")
(reagi/dispose (:lights-stream this))
this)
LightsGateway
(reset-lights! [this m n]
(post (:lights-stream this)
(:reset-lights-url config)
{:m m :n n}))
(flip-light! [this [x y]]
(post (:lights-stream this)
(:flip-light-url config)
{:x x :y y})))
(defn make-api-gateway [config]
(->ApiLightsGateway config))
The main change here is that the ApiLightsGateway component keeps a lights-stream which it's initialized in its start function and disposed of in its stop function using reagi.

I also use, reagi's deliver function to feed the lights-stream with the response that is taken from the channel that cljs-http returns when we make a post request to the server.

Next,the lights name space:

(ns kata-lights-out.lights
(:require
[reagent.core :as r]
[com.stuartsierra.component :as component]
[kata-lights-out.lights-gateway :as lights-gateway]
[reagi.core :as reagi]))
(def ^:private light-off 0)
(defn light-off? [light]
(= light light-off))
(defn- listen-to-lights-updates! [{:keys [lights-stream lights]}]
(->> lights-stream
(reagi/map #(reset! lights %))))
(defprotocol LightsOperations
(reset-lights! [this])
(flip-light! [this pos]))
(defrecord Lights [lights-gateway m n]
component/Lifecycle
(start [this]
(println ";; Starting lights component")
(let [this (assoc this
:lights-stream (:lights-stream lights-gateway)
:lights (r/atom []))
this (assoc this :lights-gateway lights-gateway)]
(listen-to-lights-updates! this)
(reset-lights! this)
this))
(stop [this]
(println ";; Stopping lights component")
this)
LightsOperations
(reset-lights! [this]
(lights-gateway/reset-lights! (:lights-gateway this) m n))
(flip-light! [this pos]
(lights-gateway/flip-light! (:lights-gateway this) pos)))
(defn all-lights-off? [lights]
(every? light-off? (flatten lights)))
(defn make-lights [m n]
(map->Lights {:m m :n n}))
Notice how the dependency on core.async disappears and the code to update the lights atom is now a subscription to the lights-stream (look inside the listen-to-lights-updates! function). This new code is much easier to read and is at a higher level of abstraction than the one using core.async in previous versions of the exercise.

Now the lights-view name space:

(ns kata-lights-out.lights-view
(:require
[reagent.core :as r]
[kata-lights-out.lights :as lights]
[reagi.core :as reagi]
[com.stuartsierra.component :as component]))
(defn- all-lights-off-message-content [config lights]
(if (lights/all-lights-off? lights)
(:success-message config)
{:style {:display :none}}))
(defn- all-lights-off-message-component [config lights]
[:div#all-off-msg
(all-lights-off-message-content config lights)])
(defn- render-light [{:keys [light-on light-off]} light]
(if (lights/light-off? light)
light-off
light-on))
(defn- light-component [config clicked-light-positions i j light]
^{:key (+ i j)}
[:button
{:on-click #(reagi/deliver clicked-light-positions [i j])}
(render-light config light)])
(defn- row-lights-component [config clicked-light-positions i row-lights]
^{:key i}
[:div (map-indexed (partial light-component config clicked-light-positions i) row-lights)])
(defn- home-page [config clicked-light-positions lights-component]
(fn []
(let [lights (:lights lights-component)]
[:div [:h2 (:title config)]
(map-indexed (partial row-lights-component config clicked-light-positions) @lights)
[all-lights-off-message-component config @lights]])))
(defn- flip-light-when-clicked [lights-component clicked-light-positions]
(->> clicked-light-positions
(reagi/map #(lights/flip-light! lights-component %))))
(defprotocol View
(mount [this]))
(defrecord LightsView [lights-component config]
component/Lifecycle
(start [this]
(println ";; Starting LightsOutView component")
(let [this (assoc this :clicked-light-positions (reagi/events))]
(mount this)
this))
(stop [this]
(println ";; Stopping LightsOutView component")
(reagi/dispose (:clicked-light-positions this))
this)
View
(mount [{:keys [clicked-light-positions]}]
(flip-light-when-clicked
lights-component clicked-light-positions)
(r/render
[home-page config clicked-light-positions lights-component]
(.getElementById js/document "app"))))
(defn make [config]
(map->LightsView {:config config}))
Here I also used reagi to create a stream of clicked-light-positions. Again the use of FRP makes the handling of clicks much simpler (in previous versions a callback was being used to do the same).

Another change to notice is that we made the view a component (LightsView component) in order to properly create and dispose of the clicked-light-positions stream.

Finally, this is the core name space where all the components are composed together:

(ns kata-lights-out.core
(:require
[kata-lights-out.lights-view :as lights-view]
[com.stuartsierra.component :as component]
[kata-lights-out.lights :as lights]
[kata-lights-out.lights-gateway :as lights-gateway]))
(enable-console-print!)
(defn init! [m n]
(component/start
(component/system-map
:lights-gateway (lights-gateway/make-api-gateway
{:reset-lights-url "http://localhost:3000/reset-lights"
:flip-light-url "http://localhost:3000/flip-light"})
:lights-component (component/using
(lights/make-lights m n)
[:lights-gateway])
:lights-view (component/using
(lights-view/make
{:success-message "Lights out, Yay!"
:light-on "1"
:light-off "0"
:title "Kata Lights Out"})
[:lights-component]))))
(init! 3 3)
This was a nice practice to learn more about doing FRP with reagi. I really like the separation of concerns and clarity that FRP brings with it.

You can find my code in these two GitHub repositories: the server and the client (see the master branch).

You can check the changes I made to use reagi here (see the commits made from the commit d51d2d4 (using a stream to update the lights) on).

Ok, that's all, next I'll start posting a bit about re-frame.

Tuesday, September 20, 2016

Kata: Variation on Lights Out, introducing component library

Recently at a Clojure Barcelona Developers event, we had a refactoring session in which we introduced Stuart Sierra's component library in a code that was already done: our previous solution to the Lights out kata.

First, we put the code in charge of talking to the back end and updating the lights atom in a separated component, ApiLightsGateway:

(ns kata-lights-out.lights-gateway
(:require
[cljs-http.client :as http]
[cljs.core.async :as async]
[com.stuartsierra.component :as component]))
(defn- extract-lights [response]
(->> response
:body
(.parse js/JSON)
.-lights
js->clj))
(defn- post [lights-channel uri params]
(async/pipeline
1
lights-channel
(map extract-lights)
(http/post uri {:with-credentials? false :form-params params})
false))
(defprotocol LightsGateway
(reset-lights! [this m n])
(flip-light! [this pos]))
(defrecord ApiLightsGateway [config]
component/Lifecycle
(start [this]
(println ";; Starting ApiLightsGateway component")
this)
(stop [this]
(println ";; Stopping ApiLightsGateway component")
this)
LightsGateway
(reset-lights! [this m n]
(post (:lights-channel this)
(:reset-lights-url config)
{:m m :n n}))
(flip-light! [this [x y]]
(post (:lights-channel this)
(:flip-light-url config)
{:x x :y y})))
(defn make-api-gateway [config]
(->ApiLightsGateway config))
Then, we did the same for the lights code which was put in the Lights component:

(ns kata-lights-out.lights
(:require
[reagent.core :as r]
[cljs.core.async :as async]
[com.stuartsierra.component :as component]
[kata-lights-out.lights-gateway :as lights-gateway])
(:require-macros
[cljs.core.async.macros :refer [go-loop]]))
(def ^:private light-off 0)
(defn light-off? [light]
(= light light-off))
(defn- listen-to-lights-updates! [{:keys [lights-channel lights]}]
(go-loop []
(when-let [new-lights (async/<! lights-channel)]
(reset! lights new-lights)
(recur))))
(defprotocol LightsOperations
(reset-lights! [this m n])
(flip-light! [this pos]))
(defrecord Lights [lights-gateway]
component/Lifecycle
(start [this]
(println ";; Starting lights component")
(let [this (assoc this
:lights-channel (async/chan)
:lights (r/atom []))
lights-channel (:lights-channel this)
lights-gateway (assoc lights-gateway
:lights-channel lights-channel)
this (assoc this :lights-gateway lights-gateway)]
(listen-to-lights-updates! this)
this))
(stop [this]
(println ";; Stopping lights component")
(async/close! (:lights-channel this))
this)
LightsOperations
(reset-lights! [this m n]
(lights-gateway/reset-lights! (:lights-gateway this) m n))
(flip-light! [this pos]
(lights-gateway/flip-light! (:lights-gateway this) pos)))
(defn all-lights-off? [lights]
(every? light-off? (flatten lights)))
(defn make-lights []
(map->Lights {}))
This component provided a place to create and close the channel we used to communicate lights data between the Lights and the ApiLightsGateway components.

Next, we used the Lights component from the view code:

(ns kata-lights-out.lights-view
(:require
[reagent.core :as r]
[kata-lights-out.lights :as lights]))
(def ^:private light-on "1")
(def ^:private light-off "0")
(defn- all-lights-off-message-content [lights]
(if (lights/all-lights-off? lights)
"Lights out, Yay!"
{:style {:display :none}}))
(defn- all-lights-off-message-component [lights]
[:div#all-off-msg
(all-lights-off-message-content lights)])
(defn- on-light-click [lights-component pos]
(lights/flip-light! lights-component pos))
(defn- render-light [light]
(if (lights/light-off? light)
light-off
light-on))
(defn- light-component [lights-component i j light]
^{:key (+ i j)}
[:button
{:on-click #(on-light-click lights-component [i j])} (render-light light)])
(defn- row-lights-component [lights-component i row-lights]
^{:key i}
[:div (map-indexed (partial light-component lights-component i) row-lights)])
(defn- home-page [lights-component]
(fn []
[:div [:h2 "Kata Lights Out"]
(map-indexed (partial row-lights-component lights-component) @(:lights lights-component))
[all-lights-off-message-component @(:lights lights-component)]]))
(defn mount [lights-component]
(r/render
[home-page lights-component]
(.getElementById js/document "app")))
And, finally, we put everything together in the lights core name space:

(ns kata-lights-out.core
(:require
[kata-lights-out.lights-view :as lights-view]
[com.stuartsierra.component :as component]
[kata-lights-out.lights :as lights]
[kata-lights-out.lights-gateway :as lights-gateway]))
(enable-console-print!)
;; -------------------------
;; Initialize app
(defrecord MainComponent [lights-component m n]
component/Lifecycle
(start [this]
(println ";; Starting main component")
(lights/reset-lights! lights-component m n)
(lights-view/mount lights-component)
this)
(stop [this]
(println ";; Stopping lights component")
this))
(defn main-component [m n]
(map->MainComponent {:n n :m m}))
(defn init! [m n]
(component/start
(component/system-map
:lights-gateway (lights-gateway/make-api-gateway
{:reset-lights-url "http://localhost:3000/reset-lights"
:flip-light-url "http://localhost:3000/flip-light"})
:lights-component (component/using
(lights/make-lights)
[:lights-gateway])
:main (component/using
(main-component m n)
[:lights-component]))))
(init! 3 3)
This was a nice practice to learn more about component and what it might take to introduce it in an existing code base.

You can find the code we produced in these two GitHub repositories: the server and the client (see the componentization branch).

You can check the changes we made to componentize the code here (see the commits made on Aug 30, 2016).

As usual it was a great pleasure to do mob programming and learn with the members of Clojure Developers Barcelona.

Wednesday, September 14, 2016

Kata: Scrabble sets in Clojure

I recently did the Scrabble sets kata in Clojure.

I used a mix of a bit of TDD, a lot of REPL-driven development (RDD) following this cycle:
  1. Write a failing test (using examples that a bit more complicated than the typical ones you use when doing only TDD).
  2. Explore and triangulate on the REPL until I made the test pass with some ugly but complete solution.
  3. Refactor the code to make it more readable.
I'm founding that this way of working in Clojure is very productive for me.

These are the tests I wrote using Midje:

(ns scrabble-sets.core-test
(:require
[midje.sweet :refer :all]
[scrabble-sets.core :as scrabble]))
(facts
"about scrabble"
(fact
"it shows the tiles that are left in the bag
in descending order of the quantity of each tile left.
In cases where more than one letter has the same quantity remaining,
those letters appear in alphabetical order, with blank tiles at the end"
(fact
"when no tiles are in play"
(scrabble/tiles-left
"") => (str "12: E\n"
"9: A, I\n"
"8: O\n"
"6: N, R, T\n"
"4: D, L, S, U\n"
"3: G\n"
"2: B, C, F, H, M, P, V, W, Y, _\n"
"1: J, K, Q, X, Z")))
(fact
"when some tiles are in play"
(scrabble/tiles-left
"PQAREIOURSTHGWIOAE_") => (str "10: E\n"
"7: A, I\n"
"6: N, O\n"
"5: T\n"
"4: D, L, R\n"
"3: S, U\n"
"2: B, C, F, G, M, V, Y\n"
"1: H, J, K, P, W, X, Z, _\n"
"0: Q")
(scrabble/tiles-left
"LQTOONOEFFJZT") => (str "11: E\n"
"9: A, I\n"
"6: R\n"
"5: N, O\n"
"4: D, S, T, U\n"
"3: G, L\n"
"2: B, C, H, M, P, V, W, Y, _\n"
"1: K, X\n"
"0: F, J, Q, Z"))
(fact
"when trying to put in play too many tiles of some kind"
(scrabble/tiles-left
"AXHDRUIOR_XHJZUQEE")
=> "Invalid input. More X's have been taken from the bag than possible."))
and this the resulting code:

(ns scrabble-sets.core
(:require
[clojure.string :as string]))
(def ^:private tiles-in-bag
{"E" 12 "A" 9 "I" 9 "O" 8 "N" 6 "R" 6 "T" 6
"L" 4 "S" 4 "U" 4 "D" 4 "G" 3 "_" 2 "B" 2
"C" 2 "M" 2 "P" 2 "F" 2 "H" 2 "V" 2 "W" 2
"Y" 2 "K" 1 "J" 1 "X" 1 "Q" 1 "Z" 1})
(def ^:private group-by-frequency
(partial group-by second))
(defn- format-tile [[freq tiles]]
(str freq ": " (string/join ", " (map str tiles))))
(defn- format-tiles [sorted-tiles]
(->> sorted-tiles
(map format-tile)
(string/join "\n")))
(defn- sort-by-frequency [tiles-in-bag]
(map (fn [[freq & [tiles]]]
[freq (sort (map first tiles))])
(sort-by key > (group-by-frequency tiles-in-bag))))
(defn- consume-tile [tiles-in-bag tile-in-play]
(update tiles-in-bag tile-in-play dec))
(defn- consume [tiles-in-play tiles-in-bag]
(reduce consume-tile tiles-in-bag tiles-in-play))
(defn- format-error-message [consumed-tiles]
(str "Invalid input. More "
(string/join ", " (map first consumed-tiles))
"'s have been taken from the bag than possible."))
(defn- display-distribution [tiles-in-bag]
(let [overconsumed-tiles (filter #(neg? (second %)) tiles-in-bag)]
(if (empty? overconsumed-tiles)
(format-tiles (sort-by-frequency tiles-in-bag))
(format-error-message overconsumed-tiles))))
(defn tiles-left [tiles-in-play]
(->> tiles-in-bag
(consume (map str tiles-in-play))
display-distribution))
See all the commits here if you want to follow the process.

You can find all the code on GitHub.

Monday, September 12, 2016

Kata: Parrot Refactoring in Clojure

I did Emily Bache's Parrot Refactoring Kata again (I did this kata in Java some time ago) but this time in Clojure. This is a very simple kata that is meant to practice the Replace Conditional with Polymorphism refactoring.

This is the initial code of the kata that have to be refactored:

(ns parrot-refactoring.core)
(def ^:private load-factor 9.0)
(def ^:private base-speed 12.0)
(defn- compute-base-speed-for-voltage [voltage]
(min 24.0 (* voltage base-speed)))
(defn speed [parrot]
(case (:type parrot)
:european-parrot
base-speed
:african-parrot
(max 0.0 (- base-speed (* load-factor (:num-coconuts parrot))))
:norwegian-blue-parrot
(if (:nailed parrot)
0.0
(compute-base-speed-for-voltage (:voltage parrot)))
(throw (Exception. "Should be unreachable!"))))
Since Clojure provides several ways of achieving polymorphism, I did two versions of the kata:

- One using protocols:

(ns parrot-refactoring.core)
(def ^:private base-speed 12.0)
(def ^:private minimum-speed 0.0)
(defprotocol Parrot
(speed [this]))
(defrecord EuropeanParrot []
Parrot
(speed [_]
base-speed))
(defrecord AfricanParrot [num-coconuts]
Parrot
(speed [_]
(let [load-factor 9.0]
(max minimum-speed (- base-speed (* load-factor num-coconuts))))))
(defrecord NorwegiaBlueParrot [voltage]
Parrot
(speed [_]
(let [maximum-speed 24.0]
(min maximum-speed (* voltage base-speed)))))
(defrecord NailedNorwegiaBlueParrot []
Parrot
(speed [_] minimum-speed))
(defn european []
(->EuropeanParrot))
(defn african [num-coconuts]
(->AfricanParrot num-coconuts))
(defn norwegian-blue-parrot [voltage]
(->NorwegiaBlueParrot voltage))
(defn nailed-norwegian-blue-parrot []
(->NailedNorwegiaBlueParrot))
This refactoring was a bit more involved than the one I did for the next version, but I managed to get rid of the exception and the resulting tests were more readable.

If you feel like following the refactoring process, check the baby steps in the commits. You can find the code in this GitHub repository.

- And another one using multimethods:

(ns parrot-refactoring.core)
(def ^:private base-speed 12.0)
(def ^:private minimum-speed 0.0)
(defmulti speed :type)
(defmethod speed :european-parrot [_]
base-speed)
(defmethod speed :african-parrot [{:keys [num-coconuts]}]
(let [load-factor 9.0]
(max minimum-speed (- base-speed (* load-factor num-coconuts)))))
(defmethod speed :norwegian-blue-parrot [{:keys [nailed voltage]}]
(let [maximum-speed 24.0]
(if nailed
minimum-speed
(min maximum-speed (* voltage base-speed)))))
(defmethod speed :default [_]
(throw (Exception. "Should be unreachable!")))
This version is much shorter and the refactoring is less involved than the previous one, but the resulting tests read much worse and the map representing the parrot has many "optional" entries.

Again, check the commits of the refactoring baby steps here, if you feel like following the refactoring process. You can find the code of this second version in this GitHub repository. I'd like to thank Emily Bache for sharing this kata.

Thursday, September 8, 2016

Mob Kata: Cellular Automata in Clojure

At this week's Clojure Developers Barcelona meetup, we did the Cellular Automata kata in Clojure.

We did mob programming and used a mix of TDD and RDD.

This is the code we wrote:

First, the tests using Midje for the rules 30 and 90:

(ns cellular-automata.rules-test
(:require
[midje.sweet :refer :all]
[cellular-automata.rules :as rules]))
(facts
"about rules"
(fact
;+-----------------------------------------------------------------+
;| Neighborhood | 111 | 110 | 101 | 100 | 011 | 010 | 001 | 000 |
;+-----------------------------------------------------------------+
;| New Center Cell | 0 | 1 | 0 | 1 | 1 | 0 | 1 | 0 |
;+-----------------------------------------------------------------+
"rule 90"
(rules/rule-90 [1 1 1]) => 0
(rules/rule-90 [1 1 0]) => 1
(rules/rule-90 [1 0 1]) => 0
(rules/rule-90 [1 0 0]) => 1
(rules/rule-90 [0 1 1]) => 1
(rules/rule-90 [0 1 0]) => 0
(rules/rule-90 [0 0 1]) => 1
(rules/rule-90 [0 0 0]) => 0)
(fact
;+-----------------------------------------------------------------+
;| Neighborhood | 111 | 110 | 101 | 100 | 011 | 010 | 001 | 000 |
;+-----------------------------------------------------------------+
;| New Center Cell | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 0 |
;+-----------------------------------------------------------------+
"rule 30"
(rules/rule-30 [1 1 1]) => 0
(rules/rule-30 [1 1 0]) => 0
(rules/rule-30 [1 0 1]) => 0
(rules/rule-30 [1 0 0]) => 1
(rules/rule-30 [0 1 1]) => 1
(rules/rule-30 [0 1 0]) => 1
(rules/rule-30 [0 0 1]) => 1
(rules/rule-30 [0 0 0]) => 0))
and the tests for the evolution and rendering of automata:

(ns cellular-automata.core-test
(:require
[midje.sweet :refer :all]
[cellular-automata.core :as automata]
[cellular-automata.rules :as rules]))
(facts
"an elementary cellular automaton"
(facts
"evolves from an initial state for some time steps
following a given rule"
(automata/evolve
rules/rule-90
[1 1 0 1 0 1 0]
5) => [[1 1 0 1 0 1 0]
[1 1 0 0 0 0 1]
[1 1 1 0 0 1 0]
[1 0 1 1 1 0 1]
[0 0 1 0 1 0 0]
[0 1 0 0 0 1 0]])
(facts
"can be rendered as text lines"
(automata/render
[[1 1 0 1 0 1 0]
[1 1 0 0 0 0 1]
[1 1 1 0 0 1 0]]) => "xx x x \nxx x\nxxx x "))
This is the corresponding code for the rules:

(ns cellular-automata.rules)
(def rule-90
{[1 1 1] 0
[1 1 0] 1
[1 0 1] 0
[1 0 0] 1
[0 1 1] 1
[0 1 0] 0
[0 0 1] 1
[0 0 0] 0})
(def rule-30
{[1 1 1] 0
[1 1 0] 0
[1 0 1] 0
[1 0 0] 1
[0 1 1] 1
[0 1 0] 1
[0 0 1] 1
[0 0 0] 0})
view raw ca_rules.clj hosted with ❤ by GitHub
and for the automaton evolution and rendering:

(ns cellular-automata.core
(:require
[clojure.string :as string]))
(def ^:private representations
{0 " "
1 "x"})
(defn- extract-neighborhoods [state]
(partition 3 1 (repeat 0) (cons 0 state)))
(defn- evolve-once [rule state]
(mapv rule (extract-neighborhoods state)))
(defn evolve [rule initial-state time-steps]
(->> initial-state
(iterate (partial evolve-once rule))
(take (inc time-steps))))
(defn- render-state [line]
(apply str (map representations line)))
(defn render [states]
(->> states
(map render-state)
(string/join "\n")))
view raw ca_core.clj hosted with ❤ by GitHub
Printing on the REPL the result of rendering the Rule 90 automaton evolution during 15 steps, we obtain a nice Sierpinski triangle :

(doseq
[line (render
(evolve
rules/rule-90
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
15))]
(print line))
x
x x
x x
x x x x
x x
x x x x
x x x x
x x x x x x x x
x x
x x x x
x x x x
x x x x x x x x
x x x x
x x x x x x x x
x x x x x x x x
x x x x x x x x x x x x x x x x => nil
You can find the code in this GitHub repository.

As usual, it was a pleasure to meet and program with Clojure Developers Barcelona members.

Friday, September 2, 2016

Kata: Varint in Clojure using Midje and test.check

In last week's Barcelona Software Craftsmanship Dojo we did the Varint kata created by Eric Le Merdy.

Since I was facilitating it, I couldn't code during the event.

Once I got home, I did it using Clojure.

These are the tests using Midje and Clojure test.check libraries:

(ns varint.core-test
(:require
[varint.core :refer :all]
[midje.sweet :refer :all]
[clojure.test.check.clojure-test :refer [defspec]]
[clojure.test.check.generators :as gen]
[clojure.test.check.properties :as prop]))
(facts
"about varint"
(facts
"encoding numbers under 128"
(encode 1) => "00000001"
(encode 8) => "00001000"
(encode 127) => "01111111")
(facts
"encoding numbers greater or equal than 128"
(encode 300) => "1010110000000010")
(facts
"decoding varints"
(decode "1010110000000010") => 300))
(defspec coding-and-decoding
1000
(prop/for-all [num (gen/large-integer* {:min 0})]
(= (-> num encode decode) num)))
and this is the resulting code:

(ns varint.core)
(defn- pad-left [length element bin-num]
(concat (repeat (- length (count bin-num)) element) bin-num))
(defn- add-most-significat-bits [bytes]
(flatten (concat (map #(cons "1" %) (butlast bytes))
(cons "0" (last bytes)))))
(defn- partition-in-blocks-of [block-size coll]
(partition-all block-size block-size coll))
(defn- bin-str->bytes [bin-str]
(->> bin-str
reverse
(partition-in-blocks-of 7)
(map reverse)
(map (partial pad-left 7 "0"))))
(defn- int->bin-str [num]
(Long/toBinaryString num))
(def ^:private drop-most-significat-bits (partial map rest))
(defn- varint->bytes [varint]
(->> varint
(partition-in-blocks-of 8)
drop-most-significat-bits))
(defn- bytes->bin-str [bytes]
(-> bytes
reverse
flatten))
(defn- int-pow [b exp]
(reduce * (repeat exp b)))
(defn- char->int [ch]
(Integer/parseInt (str ch)))
(def ^:private bin-str->bits (partial map char->int))
(defn- bits->int [bits]
(->> bits
reverse
(map-indexed #(* %2 (int-pow 2 %1)))
(reduce +)))
(defn- bin-str->int [bin-str]
(-> bin-str
bin-str->bits
bits->int))
(defn- bytes->varint [bytes]
(->> bytes
add-most-significat-bits
(apply str)))
(defn encode [num]
(-> num
int->bin-str
bin-str->bytes
bytes->varint))
(defn decode [varint]
(-> varint
varint->bytes
bytes->bin-str
bin-str->int))
view raw varint.core.clj hosted with ❤ by GitHub
I used a mix of a bit of TDD, a lot of REPL-driven development (RDD) and some property-based testing.

Basically, the cycle I followed was like this:
  1. Write a failing test (using more complicated examples than the typical ones you use when doing only TDD).
  2. Explore and triangulate on the REPL until I made the test pass with some ugly complete solution.
  3. Refactor the code to make it more readable.
I've noticed that when I mix TDD and RDD, I end up doing bigger steps and keeping less tests than when doing only TDD. I think this is because most of the baby steps and "triangulation tests" are done on the REPL which gives you a much faster feedback cycle.

This way I wrote both encode and decode functions.

Once I had then working with a few examples, I added property-based tests using Clojure test.check library (a QuickCheck like library for Clojure) to automatically explore more examples by checking that the property of "decoding and encoded number returns the number" held for 1000 randomly generated examples.

I think that these three techniques are complementary and its combination makes me more productive.

To document the development process I commit after each TDD green step and after each refactoring. I also committed the REPL history.

See all the commits here if you want to follow the process.

You can find all the code on GitHub.