https://kotlinlang.org logo
k

kioba

01/11/2019, 4:45 PM
In Scala you can destruct a type with pattern matching. It comes quite handy when we have to work with containers. An example to it is:
Copy code
def listToString(list: List[String]): String = list match {
    case s :: rest => s + " " + listToString(rest)
    case Nil => ""
}
would it make sense to add a similar pattern matching for the destructuring declaration? the example above could be replaced with `fold`/`reduce` and mixing it with
windowed
but if the list length is zero we would get an exception
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
with pattern matching this could be automatically run to the
case Nil => ""
. The compiler also could check for unsatisfied cases just like it does right now when we match agains for enum or sealed class types
d

Dico

01/11/2019, 6:13 PM
Copy code
if (list.isNotEmpty()) list.first() + " " + listToString(list.drop(1))
else ""
I get that it's not pattern matching but I think this is more readable.
k

kioba

01/11/2019, 6:43 PM
thanks for the solution, it is very kind of you. What I am really looking for is not a solution for this specific problem, Instead I am looking for what we all think about a similar language feature
d

Dico

01/11/2019, 9:11 PM
I know that pattern matching is on the table, although I don't know which version of kotlin is targeted.
I think the first version will not support collections like you're showing here, too
Maybe after collection literals are added, it might be supported using those and some kind of syntax that indicates the remainder of the collection
assuming a list literal might take the form of
[element1, element2, element3]
you might be able to do
Copy code
when (list) {
    [first, *remaining] -> first + " " + listToString(remaining)
    else -> ""
}
Keep in mind that this is highly speculative, and I personally still think it's not very readable.
It's more of a cool feature than one that is particularly useful
it would be interesting if you could apply a pattern to each element as well though
Copy code
when (list) {
    [Person("Karoly", age), *remaining] -> println(age)
}
Again, collection literals might never be added, I'm just speculating and demonstrating that your feature request might be quite far from being made a reality.
e

elizarov

01/12/2019, 1:44 PM
@kioba To start thinking about pattern matching seriously we need use-cases on the table where it helps (as in, allows to write more readable code). Your use-case is not of this kind, so it does not help in this discussion at all.
👍 1
k

kioba

01/15/2019, 12:18 PM
Thanks! what I have seen so far is that matching could help with recursion on a list. and the following issue could be easily just matched without checking the size:
Copy code
if(list.size > 3)
      doMore(list[0], list[1], list[2])
      rec (list.drop(3))
    else if (list.size == 3)
      do3(list[0], list[1], list[2])
    else if (list.size == 2)
      do2(...)
    else if(list.isEmpty())
      do0()
could be replaced with the following:
Copy code
when(list) {
  (first, second, third, rest) -> doMore(); rec(rest)
  (first, second, third, null) -> do3()
  (first, second, null) -> do2()
  (null) -> do0()
}
I personally find it readable and helpful to check for size, and destruct the container into components. Also matching might be able to warn agains left out cases for example in my example the single element list case.
d

Dico

01/15/2019, 12:23 PM
I don't support that syntax. I think using
null
to indicate that the list ended is horrible. Moreover, you're not using the variables in the matches, I assume you left that out.
k

kioba

01/15/2019, 12:27 PM
do you have any suggestions? I am open for new ideas
d

Dico

01/15/2019, 12:31 PM
Well, I think you need a stronger use case argument first.
Can you expand on the list recursion for example?
e

elizarov

01/15/2019, 3:33 PM
I’d don’t see how existing syntax for list recursion is somehow worse:
Copy code
when (list.size) {
    0 -> do0()
    2 -> do2()
    3 -> do3()
    else -> { doMore(); rest(list.subList(3, list.size)) }
}
For example, this way I immediately see that the case for size=1 was forgotten.
👍🏻 2
k

kioba

01/15/2019, 7:11 PM
you are right, it could be done differently. Thanks for the feedbacks! 🙂
4 Views