想象一下,我在 Scala 中有一個回傳單位值的函式。該函式在開始時進行了某個測驗,并得出結論,它可以停止,即已經回傳。只放一個 return 陳述句(沒有任何東西)并離開函式是否安全?
uj5u.com熱心網友回復:
命令式副作用代碼在 Scala 中大多是非慣用的,因此您將找不到任何關于如何在 Scala 中撰寫命令式副作用代碼的確切指導。
聽起來你在談論一個典型的保護條款風格,比如
def procedureWithGuard(): Unit =
if nothingToDo then return
doTheExpensiveThing()
procedureWithGuard()
這是非常好的命令式風格。它只是不是完美的 Scala 風格,但這不是因為早期return,而是因為使用了一般的副作用。
請注意,Scala 3 中有一個變化:過去,return嵌套匿名函式中的 areturn來自最接近的詞法封閉方法,即在
def returnFromNestedFunction: Boolean =
someCollection.foreach(x => if x % 2 == 0 then return true)
false
兩個returns 都return來自方法returnFromNestedFunction,即使第一個return實際上是在apply一些自動生成的Function1[T, Boolean]. 這需要編譯器跳過一些障礙,因為 Scala 支持的大多數目標平臺(JVM、ECMAScript 和過去的 .NET)根本不支持return從一種方法到另一種方法的 ing,而且它們也不支持GOTO跨方法。
這是在斯卡拉實作的方式是,內部return被編譯成throw一個特殊的例外,并且在它回傳的地方來,編譯器合成相應catch。但是,這有兩個問題:
- 在所有支持的平臺上,拋出和捕獲例外都很慢,比
return. 因此,雖然看起來代碼具有 a 的性能return(實際上是免費的),但它實際上具有例外的性能(非常慢)。 - 您可能會意外地通過捕獲所有例外處理程式來破壞代碼,該處理程式會無意中捕獲編譯器生成的例外。
出于這個原因,returnScala 3 中不推薦使用來自嵌套匿名函式的 ing。取而代之的是,有一個庫可以輕松顯式地使用例外拋出技巧,因此沒有隱藏的性能成本(該庫使例外拋出技巧易于使用,但它并沒有隱藏涉及例外的事實)并且您不會意外捕獲您不知道的隱藏例外(因為該例外并不是首先隱藏的)。
import scala.util.control.NonLocalReturns.*
def returnFromNestedFunction = returning {
someCollection.foreach(x => if x % 2 == 0 then throwReturn(true))
false
}
請注意,乍一看并不總是很明顯您return來自嵌套的匿名函式。特別是,for-comprehensions desugar into foreach(如果沒有yield),map(如果有yield),或flatMap(如果有多個生成器)和withFilter(如果有if)。比如這段代碼其實和上面一樣,只是沒有明顯可見的匿名函式:
import scala.util.control.NonLocalReturns.*
def returnFromNestedFunction = returning {
for x <- someCollection do
if x % 2 == 0 then throwReturn(true)
false
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/395811.html
上一篇:檢查Scala類實體的運行時型別
