The question
The quiz shows this code and asks what happens if you compile and run it:
def getDouble(n: Int): Int = {
println(n * 2)
}
def mainFunction(): Unit = {
val result = getDouble(10)
println(result)
}
The options are: A, it prints 20; B, it produces errors; C, it prints 10. You answer by assigning the letter to a String named answer.
Working out the answer
Reason like the compiler, from the top.
- Read the promise. The header of
getDoubleends in: Int, so the method claims to give back anInt. - Find what the body produces. In Scala the value of a block is the value of its last expression. The last expression here is
println(n * 2). - Find the type of that expression.
printlnprints text and returnsUnit, the type that means "no useful value". - Compare. The method promised an
Intand delivers aUnit. The types don't match, so the compiler refuses the program with a type mismatch error.
The message looks like this:
-- [E007] Type Mismatch Error ---
3 | println(n * 2)
| ^^^^^^^^^^^^^^
| Found: Unit
| Required: Int
Because the program doesn't compile, mainFunction never runs, and nothing is printed. That rules out option A, which would need the program to print 20 at least once, and option C, which isn't a value the code could produce anywhere. The answer is B.
The answer in Scala
val answer: String = "B"
/* Explanation:
Notice that inside the function we only compute n * 2 but do nothing with the result afterwards, we do not return it from the function.
A function with no return statement inside it is called a "void" function and should be defined accordingly, like this:
def getDouble(n: Int): Unit = {
println(n * 2)
}
But because we defined our function as an "Int" function ( def getDouble(n: Int): Int ), Scala expects an Int to be returned from the function.
And so when Scala notices that there is no actual "return" statement inside the function, it throws an error.
*/
The details that matter:
- Printing is not returning.
printlnshows a value on the screen. It doesn't hand anything back to the caller, and the value it does produce isUnit. - The missing
returnis not the real problem. Scala doesn't require the keyword: writingn * 2as the last line would be a valid fix with noreturnat all. The error exists because the last expression has the wrong type. - Two ways to fix the function. Make the last expression an
Int, as indef getDouble(n: Int): Int = { n * 2 }, or change the promise to: Unitif printing is all you want, and then drop theval resultline, since there is no number to store.
What the program would do if it compiled
It helps to see why option A is tempting. If the header said : Unit instead of : Int, the program would compile. getDouble(10) would print 20, and result would hold (), the single value of type Unit, so the second println would print (). If the body ended with n * 2 and the header stayed : Int, the call would give back 20 and the program would print 20 once, from mainFunction. Neither is what the code as written does: it has to pass the type check first, and it fails.
Common mistakes
- Choosing A. That would be true in a language where a missing return just gives a default value. In Scala a mismatched result type is a compile error.
- Choosing C. The argument
10is never printed by this code, with or without errors. - Answering with a lowercase letter or extra text. The answer is the single string
"B". - Running the code to find out. The point of the quiz is to predict the compiler's behaviour by reading, which is a skill you need whenever a program is too large to run in your head.
