Meagan Waller

Clojure Katas: FizzBuzz

March 4th

When I am tasked with learning a new language, my step after setting up my environment, is to dive into some katas.

If you're unfamiliar with a Code Kata, this blog post is a must read. In short, a code kata is an exercise in repetition. You take a small, easily solvable problem (FizzBuzz, Coin Changer),and you solve it using TDD. The benefit of the kata isn't in solving the problem, we don't really care about the problem, the benefit is getting to know your environment, honing your tools, and approaching the problem in a different way.

The first kata I usually do when learning a new language is the FizzBuzz one. Doing the katas in Clojure was no exception, I started off with the FizzBuzz kata. The first test case for the kata is making sure that 1 generates 1.

(ns fizzbuzz.core-spec
  (:require [speclj.core :refer :all]
            [fizzbuzz.core :refer :all]))

(describe "fizzbuzz"
  (it "1 is 1"
    (should=1 (fizzbuzz 1))))

It's simple enough to make this test case pass:

(ns fizzbuzz.core)
(defn fizzbuzz [number]
  number)

This code will pass as long as the number we pass is the same as what we except, this is the case for eveything except for numbers that are divisible by 3 and 5. The next interesting test case is the one that returns fizz for 3.

...
(it "3 is fizz"
  (should= "fizz" (fizzbuzz 3)))

We make this pass like so:

(defn fizzbuzz [number]
  (if (= 3 number) "fizz" number))

The next interesting test case will be 5

(it "5 is buzz"
  (should= "buzz" (fizzbuzz 5)))

Which we can pass like so:

(defn fizzbuzz [number]
  (if (= 5 number) "buzz"
    (if (= 3 number) "fizz" number)))

Next, let's look at numbers divisble by 3 or 5


(it "6 is fizz"
  (should= "fizz" (fizzbuzz 6)))
(it "10 is buzz"
  (should= "buzz" (fizzbuzz 10)))

Modify our code to make it pass:

(defn fizzbuzz [number]
  (if (zero? (rem number 5)) "buzz"
   (if (zero? (rem number 3)) "fizz" number)))

Now, we're left with making our test pass for when it's divisible by 3 or by 5:

(it "15 is fizzbuzz"
  (should= "fizzbuzz" (fizzbuzz 15)))

We can make it pass like so:

(defn fizzbuzz [number]
  (if (and (zero? (rem number 5)) (zero? (rem number 3))) "fizzbuzz"
    (if (zero? (rem number 5)) "buzz"
     (if (zero? (rem number 3)) "fizz" number))))

However, this is kind of ugly, and doesn't display intent very well, so I refactored mine to look like this:

(defn fizz? [number]
  (zero? (rem number 3)))

(defn buzz? [number]
  (zero? (rem number 5)))

(defn fizz-buzz? [number]
  (and (fizz? number) (buzz? number)))

(defn fizzbuzz [number]
  (if (fizz-bizz? number) "fizzbuzz"
    (if (buzz? number) "buzz"
      (if (fizz? number) "fizz" number))))

That completes the FizzBuzz kata in Clojure. I've also done this Kata in Java and Ruby. I also did the Coin Changer kata in Clojure.