Scala 中為什么不建議用return

在Scala中為什么不建議用return

在Scala 中使用return的話,編譯的時候會提示 the lastest statement is method is automatically returned ,use of th return keyword is redundant(多余的)

1. 要寫函數(shù)而不是指令

函數(shù)式編程的一個重要理念就是要盡量使用代碼由無狀態(tài)的函數(shù)構(gòu)成,而不是給計算機發(fā)出指令.
eg:
    f(x) = x+1 //式1.1
是一個函數(shù).
scala 會自動將最后一個表達式的結(jié)果作為返回結(jié)果
eg:
    def f(x:Int)= x+1//式1.2
    def f(x:Int):Int = return x+1// 式1.3
從以上兩種分別使用和不適用return 的表達式來看,不適用return看起來更接近函數(shù),而使用return 則更像指令)

2. return 影響類型判斷

由于Scala中的類型自動推斷機制,會自動將最后一個表達式的類型作為返回類型,
如果使用了return語句,就會破壞類型推斷機制,需要顯示注明返回類型

3. 使用return 返回含義模糊

def add(n:Int, m:Int): Int = return n + m     //式3.1
def sum1(ns: Int*): Int = ns.foldLeft(0)(add)    //式3.2
1
2
例如上述代碼,目前來看還沒有什么問題,但是如果寫成下面的形式

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語句會直接讓它所出現(xiàn)的函數(shù)返回。也就會直接break foldLeft的循環(huán)返回結(jié)果。
再看另外一個例子:

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))
}
1首先定義一個匿名函數(shù),在調(diào)用匿名函數(shù)的時候,相當于return語句出現(xiàn)在了foo函數(shù)中。因此foo() = 1
4.NonLocalReturnControl
在scala的循環(huán)中的return實際上是通過拋異常實現(xiàn)的,編譯后發(fā)現(xiàn)

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
}
可以看到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
    }
}
1

最終得到的結(jié)果字符串則為scala.runtime.NonLocalReturnControl,并不是我們預期的結(jié)果。

5.應當怎么做

實際開發(fā)中我們會經(jīng)常遇到貌似必須使用return的時候,那應該怎么辦呢?首先,scala既然提供了return關(guān)鍵字,說明它并不是禁止使用,而是需要考慮清楚是否必須這么做。在scala認為,所有的需要使用return來break的循環(huán),都是可以通過轉(zhuǎn)化為遞歸來替代的,并且性能方面scala也專門為遞歸做了優(yōu)化。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容