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: Intgives 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
nbut 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; writingnumwithout quotes asks for a variable.
Common mistakes
- Changing the call instead of the body. Passing something other than
10changes the output, but the unresolved reference stays. - Declaring a second name. Adding
val num = nas the first line of the body also compiles and prints20, but it only works around the mismatch. Making the names agree is simpler. - Case differences.
Nandnare different names, as areNumandnum. - 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.