Skip to content
Hironobu Iga

Swift's switch next to Kotlin's when

Working mostly on iOS means re-remembering how to write Kotlin's when every time, so here the two are side by side.

Published
Updated

This article is also published elsewhere. https://iganin.hatenablog.com/entry/2019/08/14/210620

Originally written in Japanese. This is a translation of the same piece.

Introduction

Besides if/else, branching in Swift uses switch and in Kotlin when. I work on iOS most of the time, so writing a Kotlin when always costs me a moment of remembering how it goes — hence this comparison, partly as a way of learning it properly.

Environment

I used the following, both web playgrounds:

The comparison

In Kotlin’s when, you write when (value) followed by condition -> expression for what happens in each branch. The default case — when none of the listed conditions match — is written with else. Another distinguishing feature is that in Kotlin a when expression can be assigned to a variable.

enum class SampleValue {
    a,
    b,
    c,
    d
}

fun main() {
    var string = "sample"
    when (string) {
        "sample" -> {
            println("this is sample")
        }
        "hoge" -> {
            println("this is hoge")
        }
        "huga" -> {
            println("this is huga")
        }
        else -> {
            println("other")
        }
    }

    val constant = when (string) {
        "sample" -> "sample"
        else -> "others"
    }

    val sampleValue = SampleValue.a

    when (sampleValue) {
        SampleValue.a, SampleValue.b -> println("a or b")
        SampleValue.c -> println("c")
        SampleValue.d -> println("d")
    }
}

In Swift’s switch, you write switch value followed by case condition: expression. The default case — again, when nothing else matches — is written as default: expression. Unlike Kotlin, you cannot assign a switch directly to a variable in Swift. To do something similar you have to assign it as the return value of a closure.

import Foundation

let sample = "sample"
let a: String = {
    switch sample {
        case "sample": return "sample"
        default: return "other"
    }
}()

switch sample {
case "sample": print("this is sample")
case "hoge": print("this is hoge")
case "huga": print("this is huga")
default: print("this is other")
}

enum Value: Int {
    case a = 0
    case b
    case c
    case d
}

let valueSample: Value = .a

switch valueSample {
    case .a, .b: print("a or b")
    case .c: print("c")
    case .d: print("d")
}

Addendum, 29 August

Adding this after some advice on Twitter. Kotlin’s when apparently gets smart casts.

Concretely, in code like the following, when a branch runs on a type match such as is Int, x has already been cast to Int by the time you are inside the expression — so no cast is needed and you can treat it as an Int.

when (x) {
  is Int -> Do Something (x is already recognised as Int here, so x + 1 = 2)
  is String -> Do Something (recognised as String here, so x + 1 prints something like 11)
  else -> Do Something
}

[Kotlin every day] Day 9. Smart casts | DevelopersIO (Japanese)