return
语句时无法推断出返回类型呢?例如,为什么以下代码会编译通过?object Main {
def who = 5
def main(args: Array[String]) = println(who)
}
但是以下内容却不行。object Main {
def who = return 5
def main(args: Array[String]) = println(who)
}
return
语句时无法推断出返回类型呢?例如,为什么以下代码会编译通过?object Main {
def who = 5
def main(args: Array[String]) = println(who)
}
但是以下内容却不行。object Main {
def who = return 5
def main(args: Array[String]) = println(who)
}
一个方法的返回类型要么是定义该方法代码块中最后一个语句的类型,要么是在没有代码块的情况下定义它的表达式的类型。
当你在方法中使用return
时,你引入了另一个可以从方法中返回的语句。这意味着Scala无法确定该return
的类型。相反,它必须继续执行直到方法结束,然后将所有退出点组合起来以推断它们的类型,然后回到每个退出点并分配它们的类型。
这样做会增加编译器的复杂性并减慢编译速度,唯一的好处是在使用return
时不必指定返回类型。另一方面,在现有系统中,推断返回类型是从Scala已经使用的有限类型推断中免费获得的。
因此,在编译器复杂性和所获得的收益之间的平衡中,后者被认为不值得前者的代价。
这会增加编译器(和语言)的复杂性。对于像这样的东西进行类型推断,只是非常奇怪。与任何与类型推断有关的事情一样,当您有一个单独的表达式时,所有内容都可以更好地工作。分散的返回语句有效地创建了许多隐含的分支,这变得非常棘手难以统一。并不是说这特别困难,只是很棘手。例如:
def foo(xs: List[Int]) = xs map { i => return i; i }
在这里,编译器究竟推断了什么?如果编译器在显式的返回语句中进行推断,那么它需要是Any
类型。实际上,许多带有显式返回语句的方法最终都会返回Any
类型,即使你不使用非本地返回也是如此。就像我说的,难以捉摸。
除此之外,这不是应该鼓励的语言特性。除非只有一个显式返回且在函数末尾,否则显式返回并不能提高代码的清晰度。原因很容易理解,如果将代码路径视为有向图,则分散的返回语句将产生大量的隐式分支,导致图中出现奇怪的叶子节点以及主体中的许多额外路径。这太棘手了。如果你的分支都是显式的(模式匹配或者if
表达式),控制流程会更容易看到,而且如果你不依赖于具有副作用的return
语句来生成值,你的代码也将更加功能化。
所以,就像Scala中的其他“不建议”的特性一样(例如asInstanceOf
而不是as
),语言设计者故意选择使事情变得更加不愉快。再加上它引入类型推断的复杂性以及结果在除最为假想的场景外实际上没有什么用处。这样的推断对于scalac来说毫无意义。
故事的寓意是:学会不要分散你的返回语句!这是在任何语言中都很好的建议,不仅仅是Scala。
as
作为函数(但我对Scala还比较新,所以可能是我的错误)。 - Jus12return
(相关内容:https://dev59.com/Gm865IYBdhLWcg3whfBf)。 - Jus12as
函数。但是在C#中有一个as
运算符,其功能类似于Scala中的asInstanceOf
方法。很多刚接触这门语言的人都会质疑为什么Scala的类型转换机制如此冗长,答案很简单,那就是为了阻止过度使用它。 - Daniel Spiewak考虑到这个(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
...它似乎不是无意的。
我不确定为什么。也许只是为了阻止使用return
语句。:)