I understand one of the main setbacks of KEEP-213 ...
# language-proposals
n
I understand one of the main setbacks of KEEP-213 (and destructuring as it is now in the language, really) is positional vs nominal access to data, as well as Java interop. I was wondering what people might think of a nominal pattern matching approach which could possibly look like the following (taking over @jw 's original example):
Copy code
sealed class Download
data class App(val name: String, val developer: Developer) : Download()
data class Movie(val title: String, val director: Person) : Download()
val download: Download = // ...

// placeholder syntax
val result = when(download) {
  is App(.name, .developer: Person(val devName = .name))
    if (devName == "Alice") -> "Alice's app $name"
  is Movie(.title, .director: Person(val dirName = .name))
    if (dirName == "Alice") -> "Alice's movie $name"
  is App, Movie -> "Not by Alice"
}
Note how - Matching is purely nominal thanks to a 'access' operator (I chose
.
but could be
&
or nothing at all, really) - Nested patterns are achieved using
:
for a 'is-of-type' relation - Destructured properties (like
.name
) are made available in the RHS of the
when
clause - Properties can be desambiguated by explicitly declaring new variables for them - Guards can be used to match for equality - Proposed syntax is in the spirit of https://youtrack.jetbrains.com/issue/KT-21661 or https://youtrack.jetbrains.com/issue/KT-44729 If deconstruction in Java is implemented as described in https://github.com/openjdk/amber-docs/blob/master/eg-drafts/deconstruction-patterns-records-and-classes.md#translation, the deconstructed parameters could correspond to the names of those of the record that
<deconstruct>()
returns
3
I am hoping to pick up writing a compiler plugin for whatever shape of pattern matching (shout out to @mattmoore) when my day job allows it
👍 3
e
I like the direction Java is taking for value extraction on pattern matching, which is to use the same syntax as conventional variable declarations. That could be done in Kotlin too:
Copy code
val result = when (download) {
  is App(val name, val developer: Person(val name as devName))
    if (devName == "Alice") -> "Alice's app $name"
  is Movie(val title, val director: Person(val name as dirName))
    if (dirName == "Alice") -> "Alice's movie $name"
  is App, Movie -> "Not by Alice"
}
With
as
resembling import aliases. It's longer but IMO more consistent.
n
Sure, syntax aside we're suggesting the same thing :)
a
You can actually do that, I guess this also looks more kotliny:
Copy code
val result = when(val tmp = download) {
  is App -> with (tmp) {
    if (developer.name == "Alice") "Alice's app $name"
  }
  is Movie -> with(tmp) {
    if (developer.name == "Alice") "Alice's movie $name"
  }
  is App, Movie -> "Not by Alice"
}
I doubt we need a new syntax for this 🤔
n
Your example does less checks than the pattern matching one above. I think you forgot to check whether
developer
and
director
are of class
Person
To do that you would need nested whens, and that is what pattern matching is supposed to help with. Additionally, your example uses normal if else as expressions, so I believe it doesn't compile: you need to provide an 'else' there. That's where guards come in: they allow avoid a branch and move on the next one.
👍 1
Currently the only way to do the above is to nest when and have repeated branches!
a
Oh yep! 😅