Thursday, July 24, 2014

Exercism: "Meetup in Clojure"

This is my solution to the Meetup problem in Clojure.

This is the first version:

(ns meetup)
(defn leap? [year]
(let
[divisible-by? (comp zero? (partial rem year))]
(or
(divisible-by? 400)
(and
(divisible-by? 4)
(not (divisible-by? 100))))))
(defn get-months-accum-days-moduli [year month]
(let
[months-accum-days-moduli-year
[0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5]
months-accum-days-moduli-leap-year
[0, 3, 4, 0, 2, 5, 0, 3, 6, 1, 4, 6]]
(if (leap? year)
(nth months-accum-days-moduli-leap-year (- month 1))
(nth months-accum-days-moduli-year (- month 1)))))
(defrecord Date [year month day])
(defn compute-week-day [{year :year month :month day :day}]
(let
[div1 (quot (- year 1) 4)
div2 (quot (- year 1) 100)
div3 (quot (+ div2 1) 4)
div4 (int (- div1 (* 3 div3)))
week-day (rem
(+ (rem (- year 1) 7)
(rem div4 7)
(get-months-accum-days-moduli year month)
(rem day 7))
7)]
(if (zero? week-day) 7 week-day)))
(defn last-day-in-month [month year]
(let
[last-days-in-months
[31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
last-day (nth last-days-in-months (- month 1))]
(if (and (leap? year) (= month 2))
(+ 1 last-day)
last-day)))
(defn dates-in-month [month year]
(map (fn [day] (Date. year month day))
(range 1 (+ (last-day-in-month month year) 1))))
(defn is-week-day? [week-day date]
(let
[week-days {:MON 1 :TUE 2 :WED 3 :THU 4 :FRI 5 :SAT 6 :SUN 7}]
(= (week-days week-day) (compute-week-day date))))
(defn is-teenth? [{day :day}]
(let
[teenth-days (set (range 13 20))]
(teenth-days day)))
(defn days-of-month-that-is [week-day]
(comp
(partial
filter
(partial is-week-day? week-day))
dates-in-month))
(defn day-teenth [week-day]
(comp vec
vals
first
(partial filter #(is-teenth? %))
(days-of-month-that-is week-day)))
(def monteenth (day-teenth :MON))
(def tuesteenth (day-teenth :TUE))
(def wednesteenth (day-teenth :WED))
(def thursteenth (day-teenth :THU))
(def friteenth (day-teenth :FRI))
(def saturteenth (day-teenth :SAT))
(def sunteenth (day-teenth :SUN))
(defn get-week-day [pos week-day]
(comp vec
vals
pos
(days-of-month-that-is week-day)))
(def first-monday (get-week-day first :MON))
(def first-tuesday (get-week-day first :TUE))
(def first-wednesday (get-week-day first :WED))
(def first-thursday (get-week-day first :THU))
(def first-friday (get-week-day first :FRI))
(def first-saturday (get-week-day first :SAT))
(def first-sunday (get-week-day first :SUN))
(def second-monday (get-week-day second :MON))
(def second-tuesday (get-week-day second :TUE))
(def second-wednesday (get-week-day second :WED))
(def second-thursday (get-week-day second :THU))
(def second-friday (get-week-day second :FRI))
(def second-saturday (get-week-day second :SAT))
(def second-sunday (get-week-day second :SUN))
(defn third [ls] (nth ls 2))
(def third-monday (get-week-day third :MON))
(def third-tuesday (get-week-day third :TUE))
(def third-wednesday (get-week-day third :WED))
(def third-thursday (get-week-day third :THU))
(def third-friday (get-week-day third :FRI))
(def third-saturday (get-week-day third :SAT))
(def third-sunday (get-week-day third :SUN))
(defn fourth [ls] (nth ls 3))
(def fourth-monday (get-week-day fourth :MON))
(def fourth-tuesday (get-week-day fourth :TUE))
(def fourth-wednesday (get-week-day fourth :WED))
(def fourth-thursday (get-week-day fourth :THU))
(def fourth-friday (get-week-day fourth :FRI))
(def fourth-saturday (get-week-day fourth :SAT))
(def fourth-sunday (get-week-day fourth :SUN))
(def last-monday (get-week-day last :MON))
(def last-tuesday (get-week-day last :TUE))
(def last-wednesday (get-week-day last :WED))
(def last-thursday (get-week-day last :THU))
(def last-friday (get-week-day last :FRI))
(def last-saturday (get-week-day last :SAT))
(def last-sunday (get-week-day last :SUN))
view raw meetup1.clj hosted with ❤ by GitHub

To make it more interesting I decided to implement the date logic myself instead of using a Date library.

What I really didn't like about this version was that I had to generate one by one a lot of functions.

I commented in my solution that I wasn't happy with the result and that I would love to find out a way to dynamically generate all the functions that the tests were using.

Yesterday I received a nitpick from moog just saying:
"intern is your friend"
So I started to google a way to use intern to solve my problem. After a while I found this post: Metaprogramming with Clojure explaining how to use intern to dynamically generate bindings in a given namespace.

I had to do several trials in the REPL and remember to force the evaluation of a sequence with doall before getting it to work using map and a list comprehension.

This is the new version in which I managed to remove the clutter by dynamically generating all the functions that the tests use (look at the two calls to doall nearly at the end of the code). It is around 30 lines shorter:

(ns meetup)
(defn leap? [year]
(let
[divisible-by? (comp zero? (partial rem year))]
(or
(divisible-by? 400)
(and
(divisible-by? 4)
(not (divisible-by? 100))))))
(defn get-months-accum-days-moduli [year month]
(let
[months-accum-days-moduli-year
[0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5]
months-accum-days-moduli-leap-year
[0, 3, 4, 0, 2, 5, 0, 3, 6, 1, 4, 6]]
(if (leap? year)
(nth months-accum-days-moduli-leap-year (- month 1))
(nth months-accum-days-moduli-year (- month 1)))))
(defrecord Date [year month day])
(defn compute-week-day [{year :year month :month day :day}]
(let
[div1 (quot (- year 1) 4)
div2 (quot (- year 1) 100)
div3 (quot (+ div2 1) 4)
div4 (int (- div1 (* 3 div3)))
week-day (rem
(+ (rem (- year 1) 7)
(rem div4 7)
(get-months-accum-days-moduli year month)
(rem day 7))
7)]
(if (zero? week-day) 7 week-day)))
(defn last-day-in-month [month year]
(let
[last-days-in-months
[31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
last-day (nth last-days-in-months (- month 1))]
(if (and (leap? year) (= month 2))
(+ 1 last-day)
last-day)))
(defn dates-in-month [month year]
(map (fn [day] (Date. year month day))
(range 1 (+ (last-day-in-month month year) 1))))
(def week-days {'mon 1 'tues 2 'wednes 3 'thurs 4 'fri 5 'satur 6 'sun 7})
(defn is-week-day? [week-day date]
(= (week-days week-day) (compute-week-day date)))
(defn is-teenth? [{day :day}]
(let
[teenth-days (set (range 13 20))]
(teenth-days day)))
(defn days-of-month-that-is [week-day]
(comp
(partial
filter
(partial is-week-day? week-day))
dates-in-month))
(defn day-teenth [week-day]
(comp vec
vals
first
(partial filter #(is-teenth? %))
(days-of-month-that-is week-day)))
(defn third [ls] (nth ls 2))
(defn fourth [ls] (nth ls 3))
(defn get-week-day [pos week-day]
(comp vec
vals
pos
(days-of-month-that-is week-day)))
(doall
(map
#(intern 'meetup (symbol (str (name %) "teenth")) (day-teenth %))
(keys week-days)))
(def func-names ["first" "second" "third" "fourth" "last"])
(doall
(map
#(intern
'meetup
(symbol (str (first %) "-" (name (second %)) "day"))
(get-week-day (resolve (symbol(first %))) (second %)))
(for [func-name func-names
week-day (keys week-days)]
[func-name week-day])))
view raw meetup2.clj hosted with ❤ by GitHub


I'm glad because I've learned about a lot of new Clojure functions, symbol, resolve, name, intern and doall, and also used a list comprehension with for.

I'd like to thank moog for giving me a passage into a new Clojure territory.

You can nitpick my solution here or see all the exercises I've done so far in this repository.

Wednesday, July 23, 2014

A bit about JavaScript functions

Yesterday, I gave a talk about JavaScript functions in Vilanova i la Geltrú.

These are the talk slides.

The talk focused in introducing the following concepts:
  • Functions as first class entities
  • Closures
  • Higher-order functions

It was based on the readings I've done lately to learn JavaScript:

Here is the code of the examples used in the talk. Most of them were taken from Reginald Braithwaite's wonderful book. I also used an example from this other post of this blog: Strategy pattern and higher-order functions?.

I'm a shy person and it's difficult for me to talk in public but in the end I enjoyed the experience. I feel that trying to share what I've learned has improved my understanding of the topic.

I hope that the talk has somehow awaken a bit of interest for functional techniques in JavaScript among the attendants.

I'd like to thank you José Carlos for talking me into giving this talk to share what I have been learning lately about JavaScript functions and functional programming.

I'd also like to thank Edgar Costilla for letting us use Espai Feedback great facilities.

Finally, I'd like to thank the attendants for their interest and questions.

Thursday, July 17, 2014

Kata: Rotate an array in place in JavaScript

Álvaro García and I were pairing yesterday after work.

We practised coding the Rotate an array in place kata in Python.

It was great fun and we discussed about naming, scaffolding tests, closures, free variables and deleting tests.

Once back at home, I redid the kata in JavaScript. You can see the resulting code in GitHub. I commited every time I got to green and after every refactoring so you can follow the process.

In this post I just want to highlight what Álvaro and I did to optimize the code a bit.

These are the tests we kept after having a first working version of the code:

'use strict';
var ArrayRotation = require("../src/ArrayRotation.js").ArrayRotation;
describe("Array rotation in place", function() {
it("An empty array does not change", function() {
var originalArray = [];
ArrayRotation.rotateInPlace(
originalArray, 3
);
expect(originalArray).toEqual([]);
});
it("A rotation by 0 steps does not change the array", function() {
var originalArray = [1, 2];
ArrayRotation.rotateInPlace(
originalArray, 0
);
expect(originalArray).toEqual([1, 2]);
});
it("A rotation by a number of steps that is less than the array size", function() {
var originalArray = [1, 2, 3, 4];
ArrayRotation.rotateInPlace(
originalArray, 2
);
expect(originalArray).toEqual([3, 4, 1, 2]);
});
});

and this is the corresponding code:

'use strict';
var ArrayRotation = {
rotateInPlace: function(array, steps) {
var i, step,
size = array.length;
if (size === 0) {
return;
}
for (step = 0; step < steps; step++) {
for (i = 1; i < size; i++) {
swap(0, i);
}
}
function swap(position1, position2) {
var temp = array[position1];
array[position1] = array[position2];
array[position2] = temp;
}
}
};
module.exports.ArrayRotation = ArrayRotation

This code worked also for steps greater or equal that the array size, only that in that particular case it would do more work than necessary. To avoid that extra work you just need to realize that a rotation by k steps yields the same result as a rotation by n * k steps, where n is a positive integer.

Since we were practising our TDD skills, we wanted to write first a failing test that forced us to write that optimization. Not that TDD should be used for that. It was only a way to set ourselves a tiny challenge for us to practise.

We realized that we could use an assertion on the number of calls to the swap helper to force the desired change, but first we had to make the function swap accessible from the outside:

'use strict';
var ArrayRotation = {
rotateInPlace: function(array, steps) {
var i, step,
size = array.length;
if (size === 0) {
return;
}
for (step = 0; step < steps; step++) {
for (i = 1; i < size; i++) {
this.swap(array, 0, i);
}
}
},
swap: function(array, position1, position2) {
var temp = array[position1];
array[position1] = array[position2];
array[position2] = temp;
}
};
module.exports.ArrayRotation = ArrayRotation

in order to spy on it:

'use strict';
var ArrayRotation = require("../src/ArrayRotation.js").ArrayRotation;
describe("Array rotation in place", function() {
it("An empty array does not change", function() {
var originalArray = [];
ArrayRotation.rotateInPlace(
originalArray, 3
);
expect(originalArray).toEqual([]);
});
it("A rotation by 0 steps does not change the array", function() {
var originalArray = [1, 2];
ArrayRotation.rotateInPlace(
originalArray, 0
);
expect(originalArray).toEqual([1, 2]);
});
it("A rotation by a number of steps that is less than the array size", function() {
var originalArray = [1, 2, 3, 4];
ArrayRotation.rotateInPlace(
originalArray, 2
);
expect(originalArray).toEqual([3, 4, 1, 2]);
});
it("A rotation by a number of steps that is greater or equal than the array size", function() {
var originalArray = [1, 2, 3, 4];
spyOn(ArrayRotation, 'swap').andCallThrough();
ArrayRotation.rotateInPlace(
originalArray, 6
);
expect(originalArray).toEqual([3, 4, 1, 2]);
expect(ArrayRotation.swap.callCount).toBe(6);
});
});

The last test was now failing, as we intended, for making to many calls to swap.

It took just a small change to the code to make the test pass:

'use strict';
var ArrayRotation = {
rotateInPlace: function(array, steps) {
var i, step,
size = array.length;
if (size === 0) {
return;
}
for (step = 0; step < steps % size; step++) {
for (i = 1; i < size; i++) {
this.swap(array, 0, i);
}
}
},
swap: function(array, position1, position2) {
var temp = array[position1];
array[position1] = array[position2];
array[position2] = temp;
}
};
module.exports.ArrayRotation = ArrayRotation

This way we could assert that a rotation by k steps yielded the same result as a rotation by n * k steps, where n is a positive integer.

Once we had that optimization in place, we made swap private again:

'use strict';
var ArrayRotation = {
rotateInPlace: function(array, steps) {
var i, step,
size = array.length;
if (size === 0) {
return;
}
for (step = 0; step < steps % size; step++) {
for (i = 1; i < size; i++) {
swap(0, i);
}
}
function swap(position1, position2) {
var temp = array[position1];
array[position1] = array[position2];
array[position2] = temp;
}
}
};
module.exports.ArrayRotation = ArrayRotation

for which we had to stop spying on it from the tests:

'use strict';
var ArrayRotation = require("../src/ArrayRotation.js").ArrayRotation;
describe("Array rotation in place", function() {
it("An empty array does not change", function() {
var originalArray = [];
ArrayRotation.rotateInPlace(
originalArray, 3
);
expect(originalArray).toEqual([]);
});
it("A rotation by 0 steps does not change the array", function() {
var originalArray = [1, 2];
ArrayRotation.rotateInPlace(
originalArray, 0
);
expect(originalArray).toEqual([1, 2]);
});
it("A rotation by a number of steps that is less than the array size", function() {
var originalArray = [1, 2, 3, 4];
ArrayRotation.rotateInPlace(
originalArray, 2
);
expect(originalArray).toEqual([3, 4, 1, 2]);
});
it("A rotation by a number of steps that is greater or equal than the array size", function() {
var originalArray = [1, 2, 3, 4];
//spyOn(ArrayRotation, 'swap').andCallThrough();
ArrayRotation.rotateInPlace(
originalArray, 6
);
expect(originalArray).toEqual([3, 4, 1, 2]);
// expect(ArrayRotation.swap.callCount).toBe(6);
});
});

Next we examined the tests to see which ones were overlapped and could be removed. They had been useful as scaffolding to build the functionality, but once there they weren't adding much value. In our opinion keeping these scaffolding tests or not, is something that needs to be ponder in a case by case basis.

After removing those tests, I renamed the remaining tests and played a bit with augmenting the Array object prototype to finally get to the following tests:

'use strict';
var ArrayRotation = require('../src/ArrayRotation.js').ArrayRotation;
Array.prototype.rotate = function(steps) {
ArrayRotation.rotateInPlace(this, steps);
};
describe("Array rotation in place", function() {
it("A rotation by any number of steps on an empty array has no effect", function() {
var originalArray = [];
originalArray.rotate(3);
expect(originalArray).toEqual([]);
});
it("A rotation by 0 steps on a non-empty array has no effect", function() {
var originalArray = [1, 2];
originalArray.rotate(0);
expect(originalArray).toEqual([1, 2]);
});
it("A rotation by non-zero steps on a non-empty array works as expected", function() {
var originalArray = [1, 2, 3, 4];
originalArray.rotate(6);
expect(originalArray).toEqual([3, 4, 1, 2]);
});
});

I think that although this kata is very simple, you can make a lot from it and have fun.

Thanks Álvaro for the great pairing experience, I hope we'll go on having fun with other katas.

Thursday, July 10, 2014

Exercism: "Grains in Clojure"

This is my solution to the Grains problem in Clojure.

(ns grains)
(defn- grains []
(letfn
[(f [n]
(seq [n (fn [] (f (* 2 n)))]))]
(f 1N)))
(defn- stream-for-n-steps [stream n]
(letfn
[(f [i stream-rest]
(let
[pair (stream-rest)]
(when (not= i 0)
(cons (first pair)
(f (- i 1) (second pair))))))]
(f n stream)))
(defn square [sqr-num]
(last (stream-for-n-steps grains sqr-num)))
(defn total []
(reduce + 0 (stream-for-n-steps grains 64)))
view raw grains.clj hosted with ❤ by GitHub

This solution is probably not idiomatic at all. I just wanted to use a stream like in my previous Racket solution to see how different would that be in Clojure.

This was the Racket version:

#lang racket
(define (grains)
(letrec
([f
(lambda (n)
(cons n
(lambda () (f (* 2 n)) )))])
(f 1)))
(define (stream-for-n-steps stream n)
(letrec ([f
(lambda(i stream-rest)
(if (= i 0)
empty
(cons (car (stream-rest))
(f (- i 1) (cdr (stream-rest))))))])
(f n stream)))
(define (square sqr-num)
(last (stream-for-n-steps grains sqr-num)))
(define total-grains
(lambda ()
(foldr + 0 (stream-for-n-steps grains 64))))
view raw grains.rkt hosted with ❤ by GitHub

As you see they are quite different.

letfn is somehow equivalent to Racket's letrec.

My biggest problem was with cons because they behave different.

Whereas in Racket you can do:
> (cons 1 2)
'(1 . 2)
in Clojure an exception is raised when you try the same:
user=> (cons 1 2)
IllegalArgumentException 
Don't know how to create ISeq from: 
java.lang.Long  clojure.lang.RT.seqFrom (RT.java:505)
You need to write this instead:
user=> (cons 1 (cons 2 nil))
(1 2)
So in the end I used seq:
user=> (seq [1 2])
(1 2)

Another difference is that you have an integer overflow in Clojure unless you use BigInt, whereas in Racket number can be arbitrarily large.

Well, now that I've tried this. I'll try writing a more idiomatic version.

You can nitpick my solution here or see all the exercises I've done so far in this repository.

Grains problem in Racket using a home-made stream

I did the Grains problem in Racket using a home-made stream:

#lang racket
(define (grains)
(letrec
([f
(lambda (n)
(cons n
(lambda () (f (* 2 n)) )))])
(f 1)))
(define (stream-for-n-steps stream n)
(letrec ([f
(lambda(i stream-rest)
(if (= i 0)
empty
(cons (car (stream-rest))
(f (- i 1) (cdr (stream-rest))))))])
(f n stream)))
(define (square sqr-num)
(last (stream-for-n-steps grains sqr-num)))
(define total-grains
(lambda ()
(foldr + 0 (stream-for-n-steps grains 64))))
view raw grains.rkt hosted with ❤ by GitHub

The stream is the function grains which returns a pair containing the first value and the generator of the rest of the stream.

The stream-for-n-steps helper gets n values from the stream.

Probably there is a function to do this directly in Racket but I wanted to remember what we did in the Coursera Programming Languages course.

Now I want to do something similar in Clojure.

Tuesday, July 8, 2014

Exercism: "Space Age in Clojure"

This is my solution to the Space Age problem in Clojure.

In the first working iteration I made all "on-planet" functions use the on-earth function.
I also used let forms to avoid magic numbers.
It has a lot of duplication:

(ns space-age)
(defn on-earth [seconds]
(let
[seconds-per-earth-year 31557600.0]
(/ seconds seconds-per-earth-year)))
(defn on-mercury [seconds]
(let
[orbital-period-in-earth-years 0.2408467]
(/ (on-earth seconds) orbital-period-in-earth-years)))
(defn on-venus [seconds]
(let
[orbital-period-in-earth-years 0.61519726]
(/ (on-earth seconds) orbital-period-in-earth-years)))
(defn on-mars [seconds]
(let
[orbital-period-in-earth-years 1.8808158]
(/ (on-earth seconds) orbital-period-in-earth-years)))
(defn on-jupiter [seconds]
(let
[orbital-period-in-earth-years 11.862615]
(/ (on-earth seconds) orbital-period-in-earth-years)))
(defn on-saturn [seconds]
(let
[orbital-period-in-earth-years 29.447498]
(/ (on-earth seconds) orbital-period-in-earth-years)))
(defn on-uranus [seconds]
(let
[orbital-period-in-earth-years 84.016846]
(/ (on-earth seconds) orbital-period-in-earth-years)))
(defn on-neptune [seconds]
(let
[orbital-period-in-earth-years 164.79132]
(/ (on-earth seconds) orbital-period-in-earth-years)))
view raw space-age1.clj hosted with ❤ by GitHub

In the next iteration I played with comp and partial to write the make-on-planet-function factory that can create "on-planet" functions as compositions of the on-earth function:

(ns space-age)
(defn on-earth [seconds]
(let
[seconds-per-earth-year 31557600.0]
(/ seconds seconds-per-earth-year)))
(defn make-on-planet-function [orbital-period-in-earth-years]
(let
[inv-period (/ 1.0 orbital-period-in-earth-years)]
(comp (partial * inv-period) on-earth)))
(def on-mercury (make-on-planet-function 0.2408467))
(def on-venus (make-on-planet-function 0.61519726))
(def on-mars (make-on-planet-function 1.8808158))
(def on-jupiter (make-on-planet-function 11.862615))
(def on-saturn (make-on-planet-function 29.447498))
(def on-uranus (make-on-planet-function 84.016846))
(def on-neptune (make-on-planet-function 164.79132))
view raw space-age2.clj hosted with ❤ by GitHub

Finally for the last version, I wrote a somehow more readable version of make-on-planet-function:

(ns space-age)
(defn on-earth [seconds]
(let
[seconds-per-earth-year 31557600.0]
(/ seconds seconds-per-earth-year)))
(defn make-on-planet-function [orbital-period-in-earth-years]
(fn [seconds]
(/ (on-earth seconds) orbital-period-in-earth-years)))
(def on-mercury (make-on-planet-function 0.2408467))
(def on-venus (make-on-planet-function 0.61519726))
(def on-mars (make-on-planet-function 1.8808158))
(def on-jupiter (make-on-planet-function 11.862615))
(def on-saturn (make-on-planet-function 29.447498))
(def on-uranus (make-on-planet-function 84.016846))
(def on-neptune (make-on-planet-function 164.79132))
view raw space-age3.clj hosted with ❤ by GitHub

You can nitpick my solution here or see all the exercises I've done so far in this repository.

Saturday, July 5, 2014

Exercism: "Extract-Transform-Load in Clojure"

This is my solution to the Extract-Transform-Load problem in Clojure.

I wrote several working versions in the REPL but this is the one that I finally submitted to Exercism as my first iteration:

(ns etl)
(defn transform [data-set]
(reduce
(fn [data [letters num]]
(reduce
(fn [data letter]
(assoc
data
(clojure.string/lower-case letter)
num))
data
letters))
{}
(zipmap (vals data-set) (keys data-set))))
view raw etl0.clj hosted with ❤ by GitHub

I used destructuring to extract the letters and score from the key-value pair which reduce was passing to the anonymous helper.

It works but it's not very readable.

In the second iteration I introduced a helper function, assoc-pairs, to improve its readability but the naming was still bad:

(ns etl (:require [clojure.string :as str]))
(defn transform [data-set]
(let
[assoc-pairs
(fn [data [letters num]]
(reduce
#(assoc %1 (str/lower-case %2) num)
data
letters))]
(reduce
assoc-pairs
{}
(zipmap (vals data-set) (keys data-set)))))
view raw etl1.clj hosted with ❤ by GitHub

So I renamed some parameters and helper functions for the third iteration:

(ns etl (:require [clojure.string :as str]))
(defn transform [letters-per-score]
(let
[associate-score-to-letters
(fn [scores-per-letter [letters score]]
(let
[associate-score-to-letter
(fn [scores-per-letter letter]
(assoc
scores-per-letter
(str/lower-case letter)
score))]
(reduce
associate-score-to-letter
scores-per-letter
letters)))]
(reduce
associate-score-to-letters
{}
(zipmap
(vals letters-per-score)
(keys letters-per-score)))))
view raw etl2.clj hosted with ❤ by GitHub

I find that, even though, using the let form to create the local bindings that gave names to the internal helper functions, associate-score-to-letters and associate-score-to-letter helps to reveal the intention of each helper function, it also creates a "parentheses vortex" that can obscure the code at the same time.

I wish Clojure would let me define these local functions just nesting the function definitions inside the enclosing function, like the functions sqrt_iter, good_enough? and improve defined inside custom_sqrt in this Scheme example (I coded it using DrRacket):

(define (average x y)
(/ (+ x y) 2))
(define (custom_sqrt x)
(define (sqrt_iter previous_guess guess)
(if (good_enough? previous_guess guess)
guess
(sqrt_iter guess
(improve guess))))
(define (good_enough? previous_guess guess)
(< (abs (- previous_guess guess))
0.001))
(define (improve guess)
(average guess (/ x guess)))
(sqrt_iter 0.0 1.0))

I think that a feature like that would help to make my Clojure solution easier to read.

You can nitpick my solution here or see all the exercises I've done so far in this repository.

Exercism: "Leap year in Clojure"

This is my solution to the Leap Year problem in Clojure:

(ns leap)
(defn leap-year? [year]
(let
[divisible-by? (comp zero? (partial rem year))
(or
(divisible-by? 400)
(and
(divisible-by? 4)
(not (divisible-by? 100))))))
view raw leap.clj hosted with ❤ by GitHub

I created a local helper, divisible-by?, using comp and partial to make the code more readable.

You can nitpick my solution here or see all the exercises I've done so far in this repository.

Friday, July 4, 2014

Exercism: "Robot name in Clojure"

This is my solution to the Robot name problem in Clojure:

(ns robot)
(defn robot []
(atom {:name ""}))
(defn robot-name [robot]
(let
[current-name (:name @robot)
random-name
(fn []
(let
[capital-letters
(map char (range (int \A) (+ (int \Z) 1)))
num-letters
(count capital-letters)]
(apply
str
(concat
(repeatedly
2
#(nth capital-letters (rand-int num-letters)))
(repeatedly
3
#(rand-int 10))))))]
(if (empty? current-name)
(:name (swap! robot assoc :name (random-name)))
current-name)))
(defn reset-name [robot]
(swap! robot assoc :name ""))
view raw robot-name.clj hosted with ❤ by GitHub

This is the first exercise in which I've used some mutable state features of Clojure, atom in this case.

It also helped me to discover the repeatedly function.

You can nitpick my solution here or see all the exercises I've done so far in this repository.

--------------------------------

Update:

After learning some new stuff, I've been able to simplify the code a bit more:

(ns robot)
(def ^:private capital-letters
(map char (range (int \A) (+ (int \Z) 1))))
(defn- random-name []
(str
(rand-nth capital-letters)
(rand-nth capital-letters)
(rand-int 1000)))
(defn robot []
(atom {:name ""}))
(defn robot-name [robot]
(let
[current-name (:name @robot)]
(if (empty? current-name)
(:name (swap! robot assoc :name (random-name)))
current-name)))
(defn reset-name [robot]
(swap! robot assoc :name ""))
view raw robot1.clj hosted with ❤ by GitHub

I used the :private true metadata key value pair to make capital-letters private, the special defn- macro instead of defn to make random-name private and the random-nth function.

You can nitpick this new version here.

Kata: Reverse Polish Notation Calculator in Clojure with Midje

I've just done the Reverse Polish Notation Calculator kata in Clojure using Midje.

These are the tests:

(ns rpn.t-core
(:use midje.sweet)
(:use [rpn.core]))
(facts
"about RPN calculator"
(fact
"a number evaluates to itself"
(evaluate "0") => 0
(evaluate "1") => 1)
(fact
"it adds several numbers"
(evaluate "0 1 +") => 1
(evaluate "1 2 5 + +") => 8)
(fact
"it subtracts several numbers"
(evaluate "0 1 -") => -1
(evaluate "1 2 5 - -") => 4)
(fact
"it multiplies several numbers"
(evaluate "0 1 *") => 0
(evaluate "1 2 5 * *") => 10)
(fact
"it divides several numbers (integer division)"
(evaluate "4 2 /") => 2
(evaluate "10 5 5 / /") => 10)
(fact
"it computes an expression with several operators"
(evaluate "4 2 / 5 + 10 * 5 6 - +") => 69
(evaluate "3 2 1 + *") => 9
(evaluate "1 2 + 4 * 5 + 3 -") => 14
(evaluate "5 1 2 + 4 * + 3 -") => 14
(evaluate "0 1 - 4 5 * *") => -20))
view raw rpn-tests.clj hosted with ❤ by GitHub

I really love how readable tests are when using Midje.

And this is the final version of the code:

(ns rpn.core
[:use [clojure [string :only [split]]]])
(defn parse-int [s]
(Integer/parseInt (re-find #"\A-?\d+" s)))
(defn parse [expression]
(let
[operators {"+" + "-" - "*" * "/" quot}
parse-token
(fn [token]
(if (contains? operators token)
(get operators token)
(parse-int token)))]
(map parse-token
(split expression #"\s"))))
(defn process-symbol [stack symbol]
(if (number? symbol)
(conj stack symbol)
(conj (pop (pop stack))
(apply symbol (take-last 2 stack)))))
(defn evaluate [expression]
(peek
(reduce
process-symbol
[]
(parse expression))))
view raw rpn.clj hosted with ❤ by GitHub

I used a mix of TDD and REPL-driven development, as I did before for the Berlin Clock kata.

Again I commited the code after every passing test and every refactor and also commited the .lein-repl-history file to document all the micro-tests I did on the REPL.

Take a look at the code and commits in this GitHub repository.

Thursday, July 3, 2014

Exercism: "Grade School in Clojure"

This is my solution to the Grade School problem in Clojure:

The first working version:

(ns school)
(defn grade [school grade-num]
(get school grade-num []))
(defn add [school name grade-num]
(assoc
school
grade-num
(conj (grade school grade-num) name)))
(defn sorted [school]
(into {}
(map
(fn [[grade students]]
[grade (sort students)])
(sort-by key school))))
view raw school1.clj hosted with ❤ by GitHub

Trying to improve its readability I introduced two local helpers in the sorted function:
sort-by-grades and sort-students-by-name.

This is the resulting version:

(ns school)
(defn grade [school grade-num]
(get school grade-num []))
(defn add [school name grade-num]
(assoc
school
grade-num
(conj (grade school grade-num) name)))
(defn sorted [school]
(let
[sort-by-grades
(partial sort-by key)
sort-students-by-name
(partial map
(fn [[grade students]]
[grade (sort students)]))]
(into
{}
(sort-students-by-name
(sort-by-grades school)))))
view raw school2.clj hosted with ❤ by GitHub

Finally, I experimented with the -> macro to see its effect on readability and got to this last version:

(ns school)
(defn grade [school grade-num]
(get school grade-num []))
(defn add [school name grade-num]
(assoc
school
grade-num
(conj (grade school grade-num) name)))
(defn sorted [school]
(let
[sort-by-grades
(partial sort-by key)
sort-students-by-name
(partial map
(fn [[grade students]]
[grade (sort students)]))]
(into
{}
(->
school
sort-by-grades
sort-students-by-name))))
view raw school3.clj hosted with ❤ by GitHub

I think the -> macro is great.

You can nitpick my solution here or see all the exercises I've done so far in this repository.

Exercism: "Phone Number in Clojure"

This is my solution to the Phone Number problem in Clojure:

The first version:

(ns phone)
(defn extract-digits [phone-number]
(let
[digits (filter #(Character/isDigit %) phone-number)
digits-length (count digits)]
(cond
(= digits-length 10) digits
(and (= digits-length 11)
(= (first digits) \1)) (rest digits)
:else (repeat 10 0))))
(defn number [phone-number]
(apply str (extract-digits phone-number)))
(defn area-code-digits [phone-number]
(take 3 (extract-digits phone-number)))
(defn area-code [phone-number]
(apply str (area-code-digits phone-number)))
(defn pretty-print [number-to-print]
(let
[digits (extract-digits number-to-print)]
(apply str
(concat "(" (area-code-digits digits) ") "
(drop 3 (take 6 digits))
"-"
(drop 6 (take 10 digits))))))
view raw phone1.clj hosted with ❤ by GitHub

And then a second one:

(ns phone)
(defn extract-digits [phone-number]
(let
[digits (filter #(Character/isDigit %) phone-number)
digits-length (count digits)]
(cond
(= digits-length 10) digits
(and (= digits-length 11)
(= (first digits) \1)) (rest digits)
:else (repeat 10 0))))
(def to-str
(partial apply str))
(def number
(comp to-str extract-digits))
(def area-code-digits
(comp (partial take 3) extract-digits))
(def area-code
(comp to-str area-code-digits))
(def extension-digits
(comp (partial drop 3) (partial take 10)))
(defn pretty-extension [extension-digits]
(to-str
(concat
(take 3 extension-digits)
"-"
(drop 3 extension-digits))))
(defn pretty-area-code [area-code]
(to-str "(" area-code ")"))
(defn pretty-print [number-to-print]
(let
[digits (extract-digits number-to-print)]
(to-str
(pretty-area-code (area-code digits))
" "
(pretty-extension (extension-digits digits)))))
view raw phone2.clj hosted with ❤ by GitHub

In this second version I removed some duplication with the help of the partial and comp functions and I also tried to make the code more readable by introducing several new helper functions.

You can nitpick my solution here or see all the exercises I've done so far in this repository.

Interesting Talk: "Failure for Fun and Profit!"

I've just watched this great talk by Kerri Miller:

Wednesday, July 2, 2014

Exercism: "Point Mutations (Hamming distance) in Clojure"

This is my solution to the Point Mutations problem in Clojure:

(ns dna)
(defn hamming-distance [strand1 strand2]
(reduce
+
(map
(fn [base1 base2]
(if (= base1 base2) 0 1))
strand1
strand2)))
view raw hamming.clj hosted with ❤ by GitHub

Compare it with the solution to the same exercise in Ruby:

class Hamming
def self.compute(strand1, strand2)
def self.base_distance(base1, base2)
def self.both_exists?(base1, base2)
not [base1, base2].any? {|base| base.nil?}
end
(both_exists?(base1, base2) and base1 != base2) ? 1 : 0
end
strand1.chars.zip(strand2.chars).map do |base1, base2|
base_distance(base1, base2)
end.reduce(:+)
end
end
view raw hamming.rb hosted with ❤ by GitHub

The version in Clojure is simpler because its map function accepts more than one collection and also takes care of the cases in which the collections have different lengths.

You can nitpick my solution here or see all the exercises I've done so far in this repository.