We have local functions; why not local properties?

Local functions are incredibly useful for separating code in a function that does not need to be exposed elsewhere:

fun parse(str: String) {
    val someList = ArrayList<String>() // variable seen inside local functions as well

    fun parsePrefix() {...}
    fun parseSuffix() {...}

    for (word in str.split('|')) {
        parsePrefix()
        // do more stuff
        parseSuffix()
    }
}

This helps structuring code inside a complex function, making it more readable and concise. And sometimes, there’s also a variable you’d like to access in multiple places, with some custom set/get code. Currently, this is the only way to do it:

fun parse(str: String) {
    var padding = 0 // gets changed
    val someList = ArrayList<String>()

    fun setPadding(pad: Int) {
        padding = pad.coerceIn(0 until someList.length)
    }
    fun first() = someList[padding]

    val someValue = padding
    // must not forget to set padding with setter
    setPadding(someOtherValue)
    first().doSomething()
}

Considering we have local functions, why would we not have local properties as well?

fun parse(str: String) {
    val someList = ArrayList<String>()
    var padding = 0 set(value) { field = value.coerceIn(0 until someList.length) }
    val first get() = someList[0]

    val someValue = padding
    // setting is easier now
    padding = someOtherValue
    first.doSomething()
}

Under the hood, these local properties could just be compiled in the same way local functions are (just like how normal properties get compiled to a field, setter and getter).

Looking at your example it seems a class would be more appropriate.

In most cases I would probably say it is a bad practice, it complicates the code. However, if you really want to do this then you can use a delegated property:

var foo: Int by object {
    operator fun getValue(nothing: Nothing?, property: KProperty<*>): Int {
        return 5
    }

    operator fun setValue(nothing: Nothing?, property: KProperty<*>, value: Int) {
        println("set to: $value")
    }
}
1 Like

Indeed, that’s not the best example, I wrote it on the spot. My case is a slightly more complex class, which can be initialised multiple ways (one of them being from a string, which needs to be parsed). This code doesn’t really need to be visible elsewhere (maybe it will be moved later elsewhere, but for now, local functions are fine since the processing is not that complex). This was merely a suggestion, since in Kotlin a getter/setter is basically just a function.