The 4 things I wish Kotlin had (as a Kotlin + Java + Scala
developer)
- Union types
- Collection literals, like Groovy:
- Native Tuples
- Destructuring-assignment and guards in pattern-matches for
when
:
We have sealed
and can get by with this, but compare the following Scala 3 to Kotlin:
def parseNumber(number: String | Int | Float): Int = number match {
case s: String => s.toInt
case i: Int => i
case f: Float => f.toInt
}
sealed interface Number {
@JvmInline value class StringNumber(val value: String) : Number
@JvmInline value class IntNumber(val value: Int) : Number
@JvmInline value class FloatNumber(val value: Float) : Number
}
// Ignore that you could just overload "parseNumber()" please, it's an example
fun parseNumber(number: Number): Int = when (number) {
is StringNumber -> number.value.toInt()
is IntNumber -> number.value
is FloatNumber -> number.value.toInt()
}
def list = [1, 2, 3]
def map = [a: 1, b: "foo", c: true]
val list = listOf(1, 2, 3)
val map = mapOf("a" to 1, "b" to "foo", "c" to true)
Example: val x = (1, "foo", true, 3.14)
Removed prior to 1.0: https://youtrack.jetbrains.com/issue/KT-2358/Drop-tuples
Removed prior to 1.0: https://youtrack.jetbrains.com/issue/KT-2359/Drop-complex-patterns
Take this example possible in modern Java and Scala:
class SimplifyZeroPass {
public static Expr simplify(Expr expr) {
return switch (expr) {
// x + 0 = x
case Add(Var(var name), Const(var value)) when value == 0 -> new Var(name);
// 0 + x = x
case Add(Const(var value), Var(var name)) when value == 0 -> new Var(name);
// x - 0 = x
case Sub(Var(var name), Const(var value)) when value == 0 -> new Var(name);
// x * 1 = x
case Mul(Var(var name), Const(var value)) when value == 1 -> new Var(name);
// 1 * x = x
case Mul(Const(var value), Var(var name)) when value == 1 -> new Var(name);
// x / 1 = x
case Div(Var(var name), Const(var value)) when value == 1 -> new Var(name);
// 0 / x = 0
case Div(Const(var value), Var(var name)) when value == 0 -> new Const(0);
// Otherwise, just return the expression
default -> expr;
};
}
}
Writing this in Kotlin is more verbose and you lose the ability to visually group the patterns together:
fun simplify(expr: Expr): Expr = when (expr) {
is Add -> {
val (left, right) = expr
when {
left is Var && right is Const && right.value == 0 -> Var(left.name)
left is Const && right is Var && left.value == 0 -> Var(right.name)
else -> expr
}
}
is Sub -> {
val (left, right) = expr
if (left is Var && right is Const && right.value == 0) Var(left.name) else expr
}
is Mul -> {
val (left, right) = expr
when {
left is Var && right is Const && right.value == 1 -> Var(left.name)
left is Const && right is Var && left.value == 1 -> Var(right.name)
else -> expr
}
}
is Div -> {
val (left, right) = expr
when {
left is Var && right is Const && right.value == 1 -> Var(left.name)
left is Const && right is Var && left.value == 0 -> Const(0)
else -> expr
}
}
else -> expr
}