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”.

Thursday, March 22, 2012

Fizz 21 - Duck Duck Mallard

It is notable in and of itself that Kotlin has language level suport for tuples.  But that alone didn't make it interesting.  What is interesting is how it is used in the when expressions pattern matching capabilities.

fun main(args : Array<String>) {
  for (i in 1..100) {
    println (
      when ( #(i % 3, i % 5) ) {
        #(0, 0) -> "FizzBuzz";
        is #(0, *) -> "Fizz";
        is #(*, 0) -> "Buzz";
        else -> i;
      }
    )
  }
}

The beginning of this solution is very pedestrian and is in fact has all been done in some fashion before in this blog.  We have a loop, we use when as an expression for println, we use a tuple as the when argument, a zero-zero tuple is a FizzBuzz.  Noting special.

Things change at line 6 and 7.  Intermixed with the standard switch handling is a pattern matching branch.  Pattern matching branches start out with the keyword is and allow for matching on types as well as tuples (negation with the !is keyword).

Using a pattern matching keyword allows us to use the * wildcard in the tuple in the branch condition.  Using a wildcard tells the compiler that (surprise!) we don't care what the value for that part of the tuple is.  So instead of having to enumerate out the full set of non-matching remainders we can just say * and not care.

This also points out the importance of order of execution.  You will not that the FizzBuzz case matches both the Fizz and the Buzz branches.  But since it is listed before those branch conditions it is evaluated first.

There are also some more interesting syntaxes planned with pattern matching for things such as Binding Patterns and Decomposer Functions but those are not implemented (yet).

No comments:

Post a Comment