Learning Clojure – Baby Steps Towards Readable Code

Posted by Brian in Clojure, Howto, Languages (October 29th, 2010)

One thing that keeps me coming back to trying to learn Clojure is the way the language forces me to think about problems in a different way. To illustrate that, I thought I’d share a simple problem and solution with you.

The sales tax on items where I live is 5.5%. 5% goes to the state of Wisconsin, and the other .5% goes to Eau Claire county. So, given a price, let’s compute the total amount owed by the customer. Most programmers have done this simple problem enough. We know that the math is basically this:

price + (price * 0.055)

Let’s break down what we know about Clojure and write this expression.

First, we know we can add two numbers together like this:

(+ 4 4)

And we know we can multiply things like this:

(* 4 4)

So by combining those concepts together, we could define our function like this:

(defn total [price] (+ price (* price 0.055)))

That works, but let’s make it more expressive.

In Clojure, things like + and * aren’t just traditional operators. They’re functions, and the parameters we pass in can also be functions.

So if we made a function that computed just the sales tax for Wisconsin at 5%:

(defn wi_tax [price] (* 0.05 price))

and another function that computed the tax for Eau Claire county at 0.5%

(defn ec_county_tax [price] (* 0.005 price))

then we can simply add the results of those two functions together with the price to get our result.

(defn total [price] (+ price (wi_tax price) (ec_county_tax price)))

When we call

(total 5)

we see that we end up with a total of 5.275 for our total price. More importantly, we’ve written readable code.

Looking into the problem more, we see we’ll need to round the number up to the nearest hundredth. Also, this illustrates how we can make better use of functions, but this code doesn’t seem to be very maintainable in its current form. There are 72 counties in Wisconsin, each with their own value for taxes. But I’m sure Clojure has a nice way of handling things like that.

Baby steps, for now.