Porting Frege FizzBuzz solution to Clojure

Yesterday I saw an interesting presentation from Devoxx by Dierk König called Frege, a Haskell for the JVM. I think he did quite a good job of bringing forth some of the benefits of functional programming and pure functions. Especially in his last example where he was demonstrating his way of solving the FizzBuzz problem in Frege (which is Haskell-like language on top of the JVM). The FizzBuzz problem can be summarized like this:

Write a program that prints the numbers from 1 to 100. But for multiples of three print “Fizz” instead of the number and for the multiples of five print “Buzz”. For numbers which are multiples of both three and five print “FizzBuzz”.

In Java a (naive) solution might look like this:

public class FizzBuzz{
	public static void main(String[] args){
		for(int i= 1; i <= 100; i++){
			if(i % 15 == 0){
				System.out.println("FizzBuzz");
			}else if(i % 3 == 0){
				System.out.println("Fizz");
			}else if(i % 5 == 0){
				System.out.println("Buzz");
			}else{
				System.out.println(i);
			}
		}
	}
}

There are several problems with this approach. For example it's hard to add additional requirements (for example if we want to print "Devoxx" for every multiple of 7), the ordering of the if statements are important, cyclomatic complexity is quite high and there's nesting etc etc. The Frege solution presented by Dierk looks like this:

fizzes = cycle ["", "", "fizz"]
buzzes = cycle ["", "", "", "", "buzz"]
pattern = zipWith (++) fizzes buzzes
numbers = map show [1..]
fizzbuzz = zipWith max pattern numbers

main _ = for (take 100 fizzbuzz) println

If you have a basic understanding of Frege/Haskell this is a nicer solution indeed (please see the presentation or have a look at Dierks e-book (chapter 8)). For a Java developer not used to this style of programming it might seem that this solution is more complex but in fact it's the other way around (remember that simple is not (necessarily) easy!). Here are some figures from Dierks talk (he talks about it at 42:05):

Fizzbuzz comparision

Anyway after seeing his presentation I wanted to port this solution to Clojure to see how close they would resemble each other. This is my attempt:

(defn fizzbuzz [length]
  (let [fizzes (cycle ["" "" "fizz"])
        buzzes (cycle ["" "" "" "" "buzz"])
        pattern (map str fizzes buzzes)
        numbers (iterate inc 1)
        fizzbuzz (map #(if (.isEmpty %1) %2 %1) pattern numbers)]
    (doseq [m (take length fizzbuzz)]
      (println m))))

This function will print the fizzbuzz sequence up until length length. As you can (hopefully) see it looks quite similar to the Frege implementation. This is also one of the things I like with functional programming. Once you learn the basic concepts and the core functions its quite easy to switch between different languages.

Leave a Reply

Your email address will not be published. Required fields are marked *