mis*_*tor 28 scala type-inference
当方法中使用显式return语句时,为什么Scala无法推断方法的返回类型?
例如,为什么以下代码编译?
object Main {
def who = 5
def main(args: Array[String]) = println(who)
}
Run Code Online (Sandbox Code Playgroud)
但以下情况并非如此.
object Main {
def who = return 5
def main(args: Array[String]) = println(who)
}
Run Code Online (Sandbox Code Playgroud)
Dan*_*ral 30
方法的返回类型是块中定义它的最后一个语句的类型,或者是在没有块的情况下定义它的表达式的类型.
在return方法内部使用时,引入另一个方法可能返回的语句.这意味着Scala无法确定return找到它的类型.相反,它必须继续直到方法结束,然后组合所有出口点以推断它们的类型,然后返回到每个退出点并分配它们的类型.
这样做会增加编译器的复杂性并减慢它的速度,因为在使用时不必指定返回类型return.另一方面,在本系统中,推断返回类型来自Scala已经使用的有限类型推断.
因此,最终,在编译器复杂性与所获得的收益之间取得平衡,后者被认为不值得前者.
Dan*_*wak 11
这会增加编译器(和语言)的复杂性.在类似的东西上进行类型推断真的很时髦.与任何类型的推理相关,当你有一个表达式时,一切都会更好.分散的返回语句有效地创建了许多隐式分支,这些分支在统一时变得非常棘手.这不是特别难,只是粘性.例如:
def foo(xs: List[Int]) = xs map { i => return i; i }
Run Code Online (Sandbox Code Playgroud)
我问你,编译器在这里推断出什么?如果编译器使用显式返回语句进行推理,则需要进行推理Any.事实上,很多带有显式返回语句的方法最终都会返回Any,即使你没有偷偷摸摸非本地回报.就像我说的那样,粘.
最重要的是,这不是一个应该鼓励的语言功能.显式返回不会提高代码清晰度,除非只有一个显式返回,并且在函数末尾.如果您将代码路径视为有向图,则很容易看出原因.正如我之前所说的,分散的返回会产生大量的隐式分支,这会在图形上产生奇怪的叶子,以及主体中的许多额外路径.这很时髦.如果您的分支都是显式的(模式匹配或if表达式),则更容易看到控制流,如果您不依赖副作用return语句来生成值,则代码将更加实用.
因此,像Scala中的其他几个"沮丧"特征(例如asInstanceOf而不是as),该语言的设计者做出了慎重的选择,使事情变得不那么令人愉快.这加上它引入类型推断的复杂性以及除了最人为的场景之外的所有结果的实际无用性.scalac尝试这种推理只是没有任何意义.
故事的道德:学会不分散你的回报!这是任何语言的好建议,而不仅仅是Scala.