25

同僚がこれを見せてくれましたが、コンパイルされていることに驚きました。

def toUpper(s: Option[String]): String = {
  s.getOrElse(return "default").toUpperCase
  //          ^^^^^^  // a return here in the closure??
}

そしてこれも機能します:

println(toUpper(Some("text"))) // TEXT
println(toUpper(None))         // default

return内部から閉鎖は許可されていないと思いました。これはいつから機能していますか?このような非ローカル リターンに関する注意事項はありますか?

4

2 に答える 2

25

セマンティクスは比較的単純です。外側のメソッドでキャッチされた をreturnスローします。最近の機能のようには見えません。バージョン 2.0 以降、Scala の変更ログには言及されていません。NonLocalReturnControltoUpperreturn

以下は、Scala 言語仕様のセクション 6.20 からの関連する説明です。

ネストされた無名関数からの戻りは、scala.runtime.NonLocalReturnException をスローしてキャッチすることで実装されます。戻り点と囲んでいるメソッドの間で例外がキャッチされると、例外が発生する可能性があります。キーの比較により、これらの例外がリターンによって終了するメソッド インスタンスによってのみキャッチされることが保証されます。

return 式自体が無名関数の一部である場合、return 式が実行される前に f の外側のインスタンスが既に返されている可能性があります。その場合、スローされた scala.runtime.NonLocalReturnException はキャッチされず、コール スタックを伝播します。

NonLocalReturnControlエスケープの例を次に示します。

var g: () => Unit = _
def f() { g = () => return }
f() // set g
g() // scala.runtime.NonLocalReturnControl$mcI$sp
于 2011-08-02T17:50:09.787 に答える
6

多かれ少なかれ、それは永遠に許可されてきました。変に思われるかもしれませんが、逆の場合も多いです。例えば:

// excessive use of braces for the sake of making scopes clearer

def findFirst[A](l: List[A])(p: A => Boolean): Option[A] = {
    for (x <- l) {
        if (p(x)) return Some(x)
    }
    None
}
于 2011-08-02T20:40:50.343 に答える