Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type inference on method return type

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) } 
like image 552
missingfaktor Avatar asked Feb 05 '10 17:02

missingfaktor


People also ask

What is meant by type inference?

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.

Does TypeScript have type inference?

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.

What is type inference in Java?

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.

What is type inference in PPL?

Type inference is the automatic deduction of the data types of specific expressions in a programming language, usually done at compile time.


2 Answers

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.

like image 50
Daniel C. Sobral Avatar answered Oct 02 '22 16:10

Daniel C. Sobral


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.

like image 40
Daniel Spiewak Avatar answered Oct 02 '22 17:10

Daniel Spiewak