Traditional high-level programming languages such as Java, C#, and C++ were designed to support imperative/procedural programming. Modern programming languages such as Kotlin make it easier to code more functional and readable solutions. In this post, I start with an imperative, non-Kotlin-esque solution for the FizzBuzz code exercise; I then refine that solution in a series of steps, explaining the following Kotlin features along the way:

FizzBuzz problem

Write a Kotlin function that accepts an integer and returns:

FizzBuzz solution

The Kotlin snippet below is a direct translation of the imperative pre-Java-8 solution here.

fun fizzBuzz(num: Int): String {
    var result = ""

    if (num % 3 == 0) {
        result = "Fizz"
    }

    if (num % 5 == 0) {
        result += "Buzz"
    }

    if (result == "") {
        result = num.toString()
    }

    return result;
}

So what’s wrong with this solution? Firstly, the variable result is mutable; we assigned it in several places in the code. The resulting code is hard to read and reason about. Kotlin helps by making the distinction between mutable variables var and their immutable counterpart val. Always thrive for immutability, i.e., using val instead of var.

But how would you do that? How would you get these if statement working without assigning result inside them? The secret is to use if as expressions instead of statements. Unlike in Java, if can return a value in Kotlin. Here is the modified code:

fun fizzBuzz(num: Int): String {
    return if (num % 3 == 0) "Fizz"
        else if (num % 5 == 0) "Buzz"
        else if (num % 3 == 0 && num % 5 == 0) "FizzBuzz"
        else "$num"
}

The solution above contains an additional improvement: changing num.toString() to its string template version “$num”. String templates allow you to use placeholders inside strings. It’s a great feature that simplifies string handling significantly, but not a massive improvement in this particular example.

This second version of the code is much better! However, we can improve the readability further by using the when expression instead of the if-else chain. If you are familiar with Java, you may find some similarities with Java switch statement. However, is it way more powerful:

This blog post provides an in-depth explanation of when expression.

Check here the final version of the code:

fun fizzBuzz(num: Int): String {
    return when {
        (num % 3 == 0) -> "Fizz"
        (num % 5 == 0) -> "Buzz"
        (num % 3 == 0 && num % 5 == 0) -> "FizzBuzz"
        else -> "$num"
    }
}