0

I was trying to create a recursive function to delete a node of a Binary Search Tree using Kotlin language. During the same I encountered this compile time error saying "Val cannot be reassigned.". I see from similar questions here that parameters of Kotlin are final, that is, they are 'val' and not 'var' in the language of Kotlin. However I want to know if there is still a way to achieve this and be able to assign values to it. I am sharing the code and commenting the ahead of the line where this error is happening.


import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KMutableProperty0

data class Node(var value:Int?){
    var data:Int? = value
    var left:Node? = null
    var right:Node? = null
}
fun insert(root:Node?, value:Int?):Node{
    var root = root
    if(root==null){
        root = Node(value)
        return root
    }
    value?.let {
        if (root.data!! > value) {
            root.left = insert(root.left, value)
        } else {
            root.right = insert(root.right, value)
        }
    }
    return root
}
fun inorder(root: Node?){
    if(root == null ) return

    root.data?.let {
        inorder(root.left)
        print("${root.data} ")
        inorder(root.right)
    }
}

fun srchDelete(root: Node?, key: Int){
    if(root == null){
        return
    }
    else if (root.data == key){
        if(root.left == null && root.right == null){
            root.data = null
            return
        }
        if(root.left != null && root.right == null){
            root = root.left //Error Here **"Val cannot be reassigned"**
        }
    }
    else {
        srchDelete(root.left, key)
        srchDelete(root.right, key)
    }
}

fun main(){
    var values = arrayOf(5,1,3,4,2,7)
    var root:Node? = null
    for(i in values){
        root = insert(root, i)
    }
    srchDelete(root, 2)
    inorder(root)
}

How can I be able to assign values in the root of type 'Node?' ?

If I put a simple code to explain my problem further. I am adding Java code that allows me to assign in function parameter and similar Kotlin code that doesn't allow me the same.

import java.util.stream.IntStream;

public class DeleteNode {
    static int[] fun (int[] arr){
        arr[0] = 1;
        arr[1] = 9;
        arr[7] = 1;
        arr = new int[9]; //Java Allows Me
        arr[0] = 9;
        return arr;
    }
    public static void main(String[] args) {
        int[] arr = new int[8];
        int[] array = fun(arr);
        IntStream.range(0, arr.length).forEach(h -> System.out.print(" " + arr[h]));
        System.out.println();
        IntStream.range(0, array.length).forEach(h -> System.out.print(" " + array[h]));

    }
}

This Java code allowed me to assign using 'new' keyword in 'arr', now similar Kotlin code.

fun list(arr:IntArray):IntArray{
    arr[0] = 1
    arr[8] = 1
    arr = IntArray(8){0} //Kotlin Doesn't Allow Me
    arr[0] = 1
    return arr
}
fun main(){
    var arr = IntArray(9){0}
    var array = list(arr)
    for(value in arr) print("$value ")
    for(value in array) print("$value ")
}

Is there a way to make Kotlin allow me to do the same too?

JavaBoi
  • 37
  • 4
  • Java/Kotlin don't have pass-by-reference semantics. – Robby Cornelissen Apr 11 '23 at 08:08
  • In Java the same thing is working, I know Java and Kotlin are pass by value but not in case of objects like for example arrays, in such cases they are pass-by-reference too. And the same procedure of code is working in java so why not in Kotlin? Just because method parameter in Kotlin are final? But there must be a way to ignore this or to make the method parameter as var and not val in some function through some means. – JavaBoi Apr 11 '23 at 08:12
  • 1
    What's the effect you expect to get from doing `root = root.left` in that location? You're not doing any further processing on `root` inside the method, and the updated `root` will not be reflected in the calling scope, neither in Java nor in Kotlin because... [everything is pass-by-value](https://stackoverflow.com/questions/40480/is-java-pass-by-reference-or-pass-by-value). – Robby Cornelissen Apr 11 '23 at 08:17
  • 1
    @JavaBoi In both Java and Kotlin we receive references to objects. In both of them we can modify these objects however we need - `val` doesn't disallow this in any way. In both Java/Kotlin we can't modify the reference itself in a way that the variable of the caller points at an entirely different object. Such feature is supported by some languages, mostly low-level, and not supported by others. – broot Apr 11 '23 at 08:54
  • 1
    BTW, by looking briefly over your code, it seems you don't really need to make it `var`. You already do `root.left = insert(root.left, value)`, so you assign to `root.left` explicitly, which is "the Java/Kotlin way". Is there anything not working as expected in your code if you remove `var root = root` and any assigning to `root`, so you do `return Node(value)`? – broot Apr 11 '23 at 09:02
  • Yes, Kotlin and Java are pass-by-value completely. But we can't assign in Kotlin function parameter unlike we do in Java. How to solve that. I am putting a small to explain my problem. – JavaBoi Apr 11 '23 at 10:49
  • I have made some edits in the last of the code, in order to explain to you my problem. I have not completed the actual code yet, but I want to do more operations in the code using "root = root.left", I want to assign different values to root, I need to. I am able to do it in Java though but I love Kotlin, so I want to learn a way to do the same in Kotlin too. – JavaBoi Apr 11 '23 at 11:06
  • In that case you can either create a new local variable using another name or re-use the same name (as you did in your first example) and suppress the warning. I believe `var root = root` worked as you expect, but it only generated a warning, correct? – broot Apr 11 '23 at 11:10
  • The reasoning for this restriction is in [this blog post](https://blog.jetbrains.com/kotlin/2013/02/kotlin-m5-1/). Basically, they deem it confusing because Kotlin also supports val and var constructor parameters that are also properties, but the meaning is different than with val and var variables. Furthermore, it’s generally considered bad style in Java to use that feature, but of course that’s a matter of opinion. – Tenfour04 Apr 11 '23 at 18:16
  • "But we can't assign in Kotlin function parameter unlike we do in Java." Assigning to function parameters in Java doesn't really affect anything the way you think it does, and it's really equivalent to just copying the function parameter to a local var with a new name and using that. Kotlin makes it clearer than in Java what's actually happening; what you can and cannot do is fundamentally the same in both languages. – Louis Wasserman Apr 12 '23 at 12:20

0 Answers0