简体   繁体   English

方法返回类型的类型推断

[英]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? 当在方法中使用显式return语句时,为什么Scala无法推断方法的返回类型?

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)
}

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. 当在方法内部使用return ,会引入另一个语句,该方法可能会从该语句中返回。 That means Scala can't determine the type of that return at the point it is found. 这意味着Scala无法在找到return时确定该return的类型。 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 . 这样做会增加编译器的复杂性并减慢其速度,因为唯一的好处就是在使用return时不必指定返回类型。 In the present system, on the other hand, inferring return type comes for free from the limited type inference Scala already uses. 另一方面,在本系统中,推断返回类型是从Scala已经使用的有限类型推断中免费获得的。

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. 分散的return语句有效地创建了很多隐式分支,这些分支很难统一。 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 . 如果编译器正在使用显式return语句进行推断,则它必须为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. 实际上,即使您不会因非本地返回而偷偷摸摸,很多带有显式return语句的方法最终仍会返回Any 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. 控制流,看看你的分支都是明确的(模式匹配或容易得多if表达式)和你的代码将变得更加实用,如果你不依赖于副作用的return报表产生价值。

So, like several other "discouraged" features in Scala (eg asInstanceOf rather than as ), the designers of the language made a deliberate choice to make things less pleasant. 因此,与Scala中的其他一些“ asInstanceOf ”功能(例如asInstanceOf而不是as )一样,该语言的设计者也做出了有选择的选择,以使事情变得不那么愉快。 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. scalac尝试这种推断完全没有任何意义。

Moral of the story: learn not to scatter your returns! 故事的寓意:学会不要分散您的回报! That's good advice in any language, not just Scala. 这是任何语言的好建议,而不仅仅是Scala。

Given this (2.8.Beta1): 鉴于此(2.8.Beta1):

object Main {
  def who = return 5
  def main(args: Array[String]) = println(who)
}
<console>:5: error: method who has return statement; needs result type
         def who = return 5

...it seems not inadvertent. ...似乎不是无意的。

I'm not sure why. 我不知道为什么。 Perhaps just to discourage the use of the return statement. 也许只是为了阻止使用return语句。 :) :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM