Destructuring in when

+1 to everything here. I think with java tentatively targeting JDK 15 for pattern matching preview that we should revisit this. I have had many occasions where destructuring a Pair or Triple would be useful:

when(Pair(int1, int2)) {
(1, ) → something()
(0, _ ) → somethingElse()
(
, 5) → anotherThing()
}
This is clearly contrived but these scenarios pop up and the alternative (nested whens) are much less powerful and more verbose and error prone. It would be a massive boon to how expressive the language is and help motivate other teams in my organization to consider kotlin.

3 Likes

I suppose JetBrains could somehow make the compiler understand pattern matching in a way that compilation would only take longer if the source code contained pattern matching logic.

It would also be nice to have some statistics on how longer a big code base using pattern matching would take to compile, compared to a similar code base without it.

With all that, developers could then decide whether they wanted to sacrifice compilation time for some more development comfort with pattern matching.

One important feature of FP languages is full blown support for pattern matching. Kotlin must learn from Scala in this case and provide pattern matching support. Java 15 anyways is coming with Pattern matching support. So, its time to revisit this.

1 Like

How can compiler deal with classes like

class MixedPair constructor(x1  : String, x2 : String) {
    val x = x1 + x2
}

or is it reserved to data class ?

Can it also include match function ( <, > for int, regexp for String …) ?

when(Pair(int1, int2)) {
    (_ > 0, _ ) -> something()
    (0, _ ) -> somethingElse()
}

Destructuring in kotlin is done using the componentN functions marked with the operator keyword. You can define them for any class starting with component1. Data classes automatically generate them.
https://kotlinlang.org/docs/reference/multi-declarations.html#destructuring-declarations

1 Like

I think introducing pattern matching would make a strong case for Kotlin when looking at Scala. Currently it is one of the most strong arguments against Kotlin.

However, I see that it would make the language more complex. But the same goes for lambda expressions. And one can see how the OP community adapted this FP feature.

3 Likes

There’s hope yet with the K2 compiler. See the comment in Aug '22:

https://youtrack.jetbrains.com/issue/KT-186/Support-pattern-matching-with-complex-patterns#focus=Comments-27-6421610.0-0

This isn’t on the roadmap yet though, but with K2 around the corner after 1.9, it shouldn’t be long before we get a better idea of what’s to come.

Add this feature to function parameters as well, no need for “when”. This is a real power of pattern matching.

fun foo(1) = 1
fun foo(2) = 1
fun foo(Int n) = foo(n-1) + foo(n-2)

cough cough Erlang cough cough.

Question of preference I suppose, but I don’t find that very idiomatic. :wink: I’d rather use a simple when:

    fun fibo(n: Int): Int =
        when (n) {
            1, 2 -> 1
            else -> fibo(n - 1) + fibo(n - 2)
        }

But for types, it’s already there, sort of, with function overloading.

… Without destructuration though, I suppose it wouldn’t be as useful as in assignments and conditions. I think it’s available in some languages, for ex. Clojure and Javascript.

Let’s see…

fun sum(Pair<Int, Int>(a, b)): Int = a + b

or

data class Person(val name: String, val age: Int, val ID: String)

fun MutableMap<String, Int>.put(Person(k, v, _)) {
    put(k, v)
}

No, I’m not convinced. Maybe there are better use-cases. :thinking:

1 Like

I prefer:

when (myVar) {
  Client(val name, ActiveMembership(PlatinumMember(var id, val membershipStartDate))) -> incrementDate(id, membershipStartDate)
  val Client(name, ActiveMembership(RegularMembership(id)))                   -> updateSettings(id)
  Client(val name, Expired(val anyMembershipType))                                -> sendWarning(anyMembershipType)
  VipClinet(val name, val membershipStatus)                                       -> freeRenewal(membershipStatus)
}
1 Like