Why does Scala fail to infer the return type of the method when there's an explicit return
statement used in the method?
For instance, why does the following code compile?
object Main { def who = 5 def main(args: Array[String]) = println(who) }
But the following doesn't.
object Main { def who = return 5 def main(args: Array[String]) = println(who) }
Type inference refers to the automatic detection of the type of an expression in a formal language. These include programming languages and mathematical type systems, but also natural languages in some branches of computer science and linguistics.
TypeScript infers types of variables when there is no explicit information available in the form of type annotations. Types are inferred by TypeScript compiler when: Variables are initialized. Default values are set for parameters.
Type inference is a Java compiler's ability to look at each method invocation and corresponding declaration to determine the type argument (or arguments) that make the invocation applicable.
Type inference is the automatic deduction of the data types of specific expressions in a programming language, usually done at compile time.
The return type of a method is either the type of the last statement in the block that defines it, or the type of the expression that defines it, in the absence of a block.
When you use return
inside a method, you introduce another statement from which the method may return. That means Scala can't determine the type of that return
at the point it is found. Instead, it must proceed until the end of the method, then combine all exit points to infer their types, and then go back to each of these exit points and assign their types.
To do so would increase the complexity of the compiler and slow it down, for the sole gain of not having to specify return type when using return
. In the present system, on the other hand, inferring return type comes for free from the limited type inference Scala already uses.
So, in the end, in the balance between compiler complexity and the gains to be had, the latter was deemed to be not worth the former.
It would increase the complexity of the compiler (and language). It's just really funky to be doing type inference on something like that. As with anything type inference related, it all works better when you have a single expression. Scattered return statements effectively create a lot of implicit branching that gets to be very sticky to unify. It's not that it's particularly hard, just sticky. For example:
def foo(xs: List[Int]) = xs map { i => return i; i }
What, I ask you, does the compiler infer here? If the compiler were doing inference with explicit return statements, it would need to be Any
. In fact, a lot of methods with explicit return statements would end up returning Any
, even if you don't get sneaky with non-local returns. Like I said, sticky.
And on top of that, this isn't a language feature that should be encouraged. Explicit returns do not improve code clarity unless there is just one explicit return and that at the end of the function. The reason is pretty easy to see if you view code paths as a directed graph. As I said earlier, scattered returns produce a lot of implicit branching that produces weird leaves on your graph, as well as a lot of extra paths in the main body. It's just funky. Control flow is much easier to see if your branches are all explicit (pattern matching or if
expressions) and your code will be much more functional if you don't rely on side-effecting return
statements to produce values.
So, like several other "discouraged" features in Scala (e.g. asInstanceOf
rather than as
), the designers of the language made a deliberate choice to make things less pleasant. This combined with the complexity that it introduces into type inference and the practical uselessness of the results in all but the most contrived of scenarios. It just doesn't make any sense for scalac to attempt this sort of inference.
Moral of the story: learn not to scatter your returns! That's good advice in any language, not just Scala.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With