Destructuring part of a list

This question is kinda all over the place (stdlib design, code golf), so apologies in advance.

We have a list of size >= 2 and we’d like to peel off the first two values into separate variables and create a new list from the remaining values, essentially something like this:

val list = listOf(1, 2, 3)
val first = list[0]
val second = list[1]
val rest = list.drop(2)

(What we actually did was introduce a List.splitAt(idx: Int): Pair<List, List> extension method:)

val list = listOf(1, 2, 3)
val (meta, rest) = list.splitAt(2)
val (first, second) = meta

But this isn’t that much better.

What we’d really like is this:

val list = listOf(1, 2, 3)
val ((first, second), *rest) = list

but this isn’t possible right now in 1.1.

What are people’s thoughts? Is there a cleaner idiomatic way to do what we’re doing?

1 Like

I think nested destructuring would be enough, so you could do:

val ((x, y), rest) = list.splitAt(2)

I think that, for the spread operator to make sense, the syntax would have to be:

val (first, second, *rest) = list

But the spread operator is not an option, since list has finite amount of componentN() and using an interface (like Iterable) for syntactical purposes is out of the question IMO.
And then you’d have to decide what kind of collection the rest variable would collect the results in.

This worked fine, without the need for an extension method, when I tried it just now:

val list = listOf(1, 2, 3)
val (first, second) = list
val rest = list.drop(2)
1 Like

This also works:

val pair = 1 to 2
val (f) = pair
println(f)  // 1

as does this:

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


val p = Person("Fred", 45)
val (name) = p
println(name)  // Fred

So it appears that the destructuring syntax, starting from component1, simply extracts as many components as you have variables and (if there are any) leaves the rest.

Using val (first, second) = list when the list is >2 in length does work, and might be what we end up doing, but still seems potentially misleading to the next reader.

It is potentially misleading if you don’t realize that destructuring declarations are not necessarily exhaustive.

The documentation doesn’t really make this clear so it’s probably not a well known point.