What the code is supposed to do
The program should print two lines:
Hey bro!
How are you doing?
The function greetAndReturn has two jobs. It prints Hey bro! itself, and it returns the string "How are you doing?". The function mainFunction calls it, stores the returned string in question and prints it. Together they should produce both lines, in that order.
The starting code prints only the second line:
fun greetAndReturn(): String {
return "How are you doing?"
println("Hey bro!")
}
What goes wrong
A return statement does two things at once: it gives a value back to the caller, and it ends the function immediately. Whatever sits below the return is never executed. Here, the println("Hey bro!") line comes after the return, so the function is already finished by the time it would run.
Following the program through shows it:
mainFunctioncallsgreetAndReturn().- The function hits
return "How are you doing?"and leaves, taking that string with it. questionis set to"How are you doing?".println(question)prints it.
The code still compiles and runs without an error. That is what makes this kind of bug easy to miss: the program is valid, it just doesn't do everything you can see written in it.
Fixing it step by step
- Decide the order of events.
Hey bro!must be printed first, and the returned text is printed afterwards bymainFunction. The function therefore has to print before it returns. - Move the
printlnline up. Put it above thereturn, inside the same function body. The text and the function don't change; only the order of the two lines does. - Keep the
returnas the last statement. Everything the function must do goes before it.
The fixed code in Kotlin
fun greetAndReturn(): String {
println("Hey bro!")
return "How are you doing?"
}
fun mainFunction() {
val question = greetAndReturn()
println(question)
}
Now the run goes like this. greetAndReturn() prints Hey bro! while it runs, then returns the string. Back in mainFunction, question holds the string, and println(question) prints it as the second line.
A few Kotlin details:
- The header
fun greetAndReturn(): Stringpromises aString. A function with a declared return type other thanUnitmust return a value on every path, and the finalreturndoes that. val question = greetAndReturn()has no type written, and none is needed: Kotlin infersStringfrom the function's return type.- The call to
greetAndReturn()is whereHey bro!gets printed. Storing the result in a variable doesn't change that; the function body runs fully when it is called.
When skipping code is the point
Ending a function early is useful when you do it on purpose. In this function, a return inside an if skips the rest of the body for some inputs only:
fun describe(n: Int): String {
if (n < 0) {
return "negative"
}
println("checked $n")
return "not negative"
}
Calling describe(-5) returns "negative" without printing anything. Calling describe(3) prints checked 3 and then returns "not negative". In the buggy code, the return has no condition, so it ends the function every time.
Common mistakes
- Printing the greeting from
mainFunctioninstead. That can print the same two lines, but the function is meant to print its greeting itself, and this lesson's code expects it there. - Deleting the
returnline. The function promises aString, so removing thereturnis a compile error. - Putting the
printlnafter thereturnin a different shape. Any statement placed after areturnthat always runs is skipped, whether it is a print, an assignment or a call. - Swapping the output order by mistake. If the text is returned and printed by the caller, it appears after everything the function printed, because the caller only prints once the function has finished.
When a function seems to skip a line, look above that line for a return.