Start learning free

LESSON 37 OF 348 · FUNCTIONS I

Unresolved Reference in Kotlin: Fixing a Wrong Variable Name

Practice Read the full explanation

Inside the code editor we've tried to define and call a function that takes a number as argument and prints the double of that number to the console.

So when we ran the code, we expected it to print:

20

but it seems like we made some mistakes because when we run our code we get an error instead.


Assignment:

Your task is to fix our code such that no errors will be produced and it will print the desired output.

STEP 1 OF 1
    Ctrl + Enter to check

    KOTLIN · FUNCTIONS I

    Buggy Code Non Existing Variable in Kotlin, explained

    Problem overview

    The program defines printDouble, a function that takes a whole number and prints twice its value. mainFunction calls it with 10, so the expected output is 20. The code you start with doesn't compile, so nothing is printed at all. Your job is to find the mistake and fix it so the program prints 20.

    fun printDouble(n: Int) {
        println(2 * num)
    }
    
    fun mainFunction() {
        printDouble(10)
    }
    

    What goes wrong

    The compiler stops with this error:

    error: unresolved reference 'num'.
        println(2 * num)
                    ^^^
    

    "Unresolved reference" means the compiler met a name and could not find anything with that name that the code is allowed to use. It points at num in the println line.

    The function header says n: Int, so the parameter is called n. Inside the body, the code asks for num. Those are two different names. Kotlin names are exact: it doesn't guess that num means n, and it doesn't care that both are meant to hold the same number. No variable called num exists in printDouble, and there is none at the top level of the file either, so the lookup fails.

    Where a name can be used

    A function body can see three kinds of names:

    • its own parameters, here n;
    • variables declared inside the body itself;
    • declarations at the top level of the file, such as other functions.

    The parameter n exists only while printDouble runs. The call printDouble(10) in mainFunction hands the value 10 to that parameter. A name that appears in none of these three places is unresolved, and the compiler reports it before the program can start.

    The fix

    Use the name the function actually declares. Change num to n in the println line:

    fun printDouble(n: Int) {
        println(2 * n)
    }
    
    fun mainFunction() {
        printDouble(10)
    }
    

    With the parameter named n, the call printDouble(10) evaluates 2 * 10 and prints 20.

    The opposite fix also works: rename the parameter to num in the header and leave the body alone:

    fun printDouble(num: Int) {
        println(2 * num)
    }
    

    Both versions print 20. The rule is only that the header and the body agree. Renaming the parameter doesn't affect the caller, because this call passes its argument by position.

    The solution in Kotlin

    fun printDouble(n: Int) {
        println(2 * n)
    }
    
    fun mainFunction() {
        printDouble(10)
    }
    

    A few details about this code:

    • The parameter's type is required. n: Int gives the name first, then a colon, then the type. Kotlin doesn't infer the types of function parameters.
    • No return type is written. The function prints and gives nothing back, so its return type is Unit, which Kotlin fills in when you leave it out.
    • Parameters are read-only. Inside the body you can read n but you can't assign a new value to it.
    • Unlike a typo in a string, a typo in a name is caught at compile time. Writing "num" in quotes would print the text; writing num without quotes asks for a variable.

    Common mistakes

    • Changing the call instead of the body. Passing something other than 10 changes the output, but the unresolved reference stays.
    • Declaring a second name. Adding val num = n as the first line of the body also compiles and prints 20, but it only works around the mismatch. Making the names agree is simpler.
    • Case differences. N and n are different names, as are Num and num.
    • Fixing only one of two uses. If you rename the parameter, every use of it in the body must change too. The compiler reports each place that still uses the old name.

    Reading the error message

    When a Kotlin program fails to compile, the message names the problem and quotes the offending line. Here the quoted name, num, is the one to compare with the function header. Whenever you see "unresolved reference", look for a misspelled name, a name used outside the function that declares it, or a missing declaration.

    Keep going with KotlinAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free