Search code examples
initializationkotlindestructuring

Initialization of val by destructuring in Kotlin


Initially I wanted to achieve

class NotationDiceRoll(notation: String) {
    val rolls: Int
    val sides: Int

    init {
        parseNotation(notation)
    }

    private fun parseNotation(notation: String) {
        rolls = 1
        sides = 4
    }
}

But Kotlin complains that "Val cannot be reassigned".

It seems that the only place where the vals can be assigned is the init block. Alright then, it is more obvious after all. So I changed it to

class NotationDiceRoll(notation: String) {
    val rolls: Int
    val sides: Int

    init {
        (rolls, sides) = parseNotation(notation)
    }

    private fun parseNotation(notation: String): Pair<Int, Int> {
        return Pair(1, 4)
    }
}

Now Kotlin complains that "Variable 'rolls' must be initialized".

It can be solved by

init {
    val(rolls, sides) = parseNotation(notation)

    this.rolls = rolls
    this.sides = sides
}

but it is less elegant.

So my question is: is the destructuring really possible only with the vals being declared on the same line?


Solution

  • This feature is called a destructuring declaration, and that's what it is, a declaration of new variables with immediate assignment to them. It's not just that variables declared with val can't be used in later destructuring, no variables declared earlier can. For example, the following doesn't work either:

    var x = 0
    var y = 0
    (x, y) = Pair(1, 2)
    

    It's worth noting though that the feature you're looking for (destructuring assignments) was one of the possible future features for Kotlin out of the 20 cards that were available to be voted on at the Kotlin 1.1 event. While the online survey is no longer up, you can see the description of the feature on this image, it's card number 15. It's a bit hard to make out, so here's what's on it:


    15 Destructuring assignments

    Kotlin already has destructuring declarations:

    val (name, address) = findPerson(...)
    

    Some users request destructuring assignments, ie. assign to multiple previously declared var's:

    var name = ...
    ...
    var address = ...
    ...
    (name, address) = findPerson(...)
    

    Do you need this feature?


    Update: here's an official doc with the proposed features, and here's the survey results.