I have written Red–black tree in Kotlin. Fun insertFixup restores balance after inserting new element (z: Node? is new element). Algorithm of tree balancin
Kotlin function parameters are read-only values and are not assignable.
You can however create a ReadWriteProperty object to pass to insertFixup
for getting/setting newNode
:
...
class BinarySearchTree {
...
fun insertFixup(zProperty: ReadWriteProperty<Any?, Node?>) {
var z by zProperty
...
fun main(args: Array<String>) {
val bst = BinarySearchTree()
var newNode: Node? = null
val newNodeProperty = object : ReadWriteProperty<Any?, Node?> {
override operator fun getValue(thisRef: Any?, property: KProperty<*>): Node? {
return newNode
}
override operator fun setValue(thisRef: Any?, property: KProperty<*>,
value: Node?) {
newNode = value
}
}
while (true) {
newNode = Node(readLine()!!.toInt())
bst.insert(newNode!!)
bst.insertFixup(newNodeProperty)
}
}
And if you are willing to use a property instead of a variable then you can use a property reference for getting/setting newNode
from insertFixup
instead:
...
class BinarySearchTree {
...
fun insertFixup(zProperty: KMutableProperty0<Node?>) {
var z by zProperty
...
var newNode: Node? = null
fun main(args: Array<String>) {
val bst = BinarySearchTree()
while (true) {
newNode = Node(readLine()!!.toInt())
bst.insert(newNode!!)
bst.insertFixup(::newNode)
}
}
// the following allow `KMutableProperty0` to be used as a read/write delegate
operator fun <T> KProperty0<T>.getValue(thisRef: Any?, property: KProperty<*>): T = get()
operator fun <T> KMutableProperty0<T>.setValue(thisRef: Any?, property: KProperty<*>,
value: T) = set(value)
I ran into this issue as well. What i did was create a data class and pass the data class as a parameter that i could then use to modify its properties.
data class SomeDataClass(
val x: Int,
val y: Int,
val z: Int
)
fun someMethod(someDataClass: SomeDataClass) {
someDataClass.z = 23 //whatever Int value you please
// more computations...
someDataClass.z = 67 // or whatever new value you need to assign.
}
fun parentMethod() {
val someDataClass = SomeDataClass()
someMethod(someDataClass)
val newZValue = someDataClass.z // someDataClass holds modified data from above
// method
}
Function parameters in Kotlin are basically read-only val
's inside the function, so z
here will always refer to the original object that was passed in.
If you need to modify what it points to while your function is running, you'll have to make a local copy of it at the beginning of the function, and then you can make that a var
.
For example, you could start your function like this, which lets you reassign this local var
later:
fun insertFixup(_z: Node?) {
var z = _z
// ...
z = z.parent
// ...
}