主页 > 新闻资讯 > 大数据编程:Scala中为什么不建议用return关键字

大数据编程:Scala中为什么不建议用return关键字

作者:张老师 浏览次数: 2021-02-01 17:17
在scala中使用return的话,编译的时候会提示the latest statement is method is automatically returned,use of th return keyword is redundant.

这个警告是说最后一个语句的结果会自动返回,不需要使用return语句。scala不建议使用return关键字,这一点在刚刚接触函数式编程的时候感觉非常难受。

大数据培训:Scala中为什么不建议用return关键字

有return会让代码结果更清晰不是么?在查阅之后,整理了以下几点不建议使用return关键字的原因。

1.要写函数而不是指令

函数式编程的一个重要理念就是要尽量使代码由无状态的函数构成,而不是给计算机发出指令。例如

f(x)=x+1//式1.1
1


是一个函数。

scala会自动将最后一个表达式的结果作为返回结果

def f(x:Int)=x+1//式1.2
def f(x:Int):Int=return x+1//式1.3
12


从以上两种分别使用和不使用return的表达方式来看,不使用return看起来更接近函数,而使用了return则更像指令。

2.return影响类型推断

scala中的类型推断机制会自动将最后一个表达式的类型作为返回类型,例如式1.2中,函数能够自动识别结果为Int类型。如果使用了return语句,就会破坏类型推断机制,需要显式注明返回类型,例如式1.3。

3.使用return返回含义模糊

有时使用了return会让代码的返回更加混乱,这个歧义主要产生于return到底返回到哪一层函数。

def add(n:Int,m:Int):Int=return n+m//式3.1
def sum1(ns:Int*):Int=ns.foldLeft(0)(add)//式3.2
12


例如上述代码,目前来看还没有什么问题,但是如果写成下面的形式

def sum2(ns:Int*):Int=ns.foldLeft(0)((n,m)=>return n+m)//式3.3
1


直观感受式3.3与3.1+3.2应该是等效的。但事实上sum1(1,2,3)=6,而sum2(1,2,3)=1.

原因就是return语句会直接让它所出现的函数返回。也就会直接break foldLeft的循环返回结果。

再看另外一个例子:

def foo:Int={
val sumR:List[Int]=>Int=_.foldLeft(0)((n,m)=>return n+m)
sumR(List(1,2,3))+sumR(List(4,5,6))
}
1234


首先定义一个匿名函数,在调用匿名函数的时候,相当于return语句出现在了foo函数中。因此foo()=1

4.NonLocalReturnControl

在scala的循环中的return实际上是通过抛异常实现的,编译后发现

return value
1


被编译成了

throw new NonLocalReturnControl(key/*metadata*/,value)
1


而NonLocalReturnControl的源码为:

class NonLocalReturnControl[@specialized T](val key:AnyRef,val value:T)extends ControlThrowable{
final override def fillInStackTrace():Throwable=this
}
123


可以看到NonLocalReturnControl异常继承了Throwable,并且为了提升性能重写了fillInStackTrace不填入堆栈信息。这样一来,如果我们在代码中为了保护代码不crash而这样写:

def fun(n:Int):String={
try{
for(i<-0 to n){
if(i<5){
}else{
return"gt"
}
}
""
}catch{
case t:Throwable=>return t.toString
}
}
12345678910111213


最终得到的结果字符串则为scala.runtime.NonLocalReturnControl,并不是我们预期的结果。

5.应当怎么做

实际开发中我们会经常遇到貌似必须使用return的时候,那应该怎么办呢?

首先,scala既然提供了return关键字,说明它并不是禁止使用,而是需要考虑清楚是否必须这么做。在scala认为,所有的需要使用return来break的循环,都是可以通过转化为递归来替代的,并且性能方面scala也专门为递归做了优化。
热点排行
推荐文章
立即申请>>