You never touched Groovy, nor did you jump on the Scala train. Clojure never attracted you; and you heard about Ceylon long after the language had already died. You are one of those old-fashioned Java folks! But now, after all those years, you want to join the cool Kotlin kids. So, where to start? Let’s discover the language together by decompiling it to Java code. Today: Pattern matching!

Today: Pattern matching

As the release of Java 21 with complete pattern matching support is around the corner[1], it’s probably a good moment to discover Kotlin’s when expression. Kotlin does not support full-blown pattern matching like Scala and future Java, but a very lightweight variant[2]. It is more of an advanced switch statement:

fun printNumbers(i: Int) =
   when (i) {
      1 -> print("one")
      2 -> print("two")
      else -> print("$i not yet supported")
   }

The decompiled Java code does indeed show a switch statement:

public static final void printNumbers(int i) {
   switch (i) {
      case 1:
         System.out.print("one");
         break;
      case 2:
         System.out.print("two");
         break;
      default:
         System.out.print(i + " not yet supported");
   }
}

Lovely! The expression is slightly more powerful than the old-fashioned Java switch, because you can also use ranges:

fun printRanges(i: Int) =
   when (i) {
      in 1..10 -> print("1 till 10")
      in 11 until 100 -> print("11 until 100")
      in 100 .. 1000 -> print("100 till 1000")
      else -> print("rest")
   }

For every case, an if-statement in shown in the Java code:

public static final void printRanges(int i) {
   if (1 <= i) {
      if (10 >= i) {
         System.out.print("1 till 10");
         return;
      }
   }

   if (11 <= i) {
      if (100 > i) {
         System.out.print("11 until 100");
         return;
      }
   }

   if (100 <= i) {
      if (1000 >= i) {
         System.out.print("100 till 1000");
         return;
      }
   }

   System.out.print("rest");
}

In addition to primitives and strings, the when expression also supports classes:

fun examine(animal: Animal) =
   when (animal) {
      is Dog -> "It's a proud dog!"
      is Cat -> "It's a lovely cat!"
      is Snake -> "Yikes, it's a snake!"
      else -> "It's some beast..."
   }

Because the JVM switch instructions work only with primitives[3], the expression is translated into a ternary expression:

public static final String examine(Animal animal) {
   return
      animal instanceof Dog   ? "It's a proud dog!" :
      animal instanceof Cat   ? "It's a lovely cat!" :
      animal instanceof Snake ? "Yikes, it's a snake!" :
                                "It's some beast...";
}

Finally, you can also use the when expression without a value. The usage basically works like a bunch of if-else statements:

fun isPositive(i: Int) =
   when {
      i >= 0 -> true
      else -> false
   }

With a silly example like the one above, the compiler is smart enough to remove the expression altogether:

public static final boolean isPositive(int i) {
   return i >= 0;
}

Well, that’s enough for one day. Stay tuned for more!


2. Full fledged pattern matching has been discussed for years though, see KT 186: Support pattern matching with complex patterns and related issues.
3. Java switch statements use the 'tableswitch' and 'lookupswitch' instructions. See also the Java Language Specification 3.10 for more information.
shadow-left