Scala中的非本地回报是新的吗?

Jea*_*let 24 scala return control-flow

一位同事刚刚向我展示了这一点,我很惊讶它汇总了:

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

这甚至有效:

println(toUpper(Some("text"))) // TEXT
println(toUpper(None))         // default
Run Code Online (Sandbox Code Playgroud)

我认为return从内部封闭是不允许的.从什么时候开始?是否有这种非本地回报的警告?

Kip*_*ros 24

语义相对简单:return将抛出一个NonLocalReturnControl被封闭方法捕获的东西toUpper.它看起来不像是最近的功能; 自2.0版以来,returnScala更改日志中没有提及.

以下是Scala语言规范第6.20节中的相关描述:

从嵌套的匿名函数返回是通过抛出和捕获scala.runtime.NonLocalReturnException来实现的.返回点和封闭方法之间的任何异常捕获都可能会看到异常.密钥比较确保这些异常仅由返回终止的方法实例捕获.

如果返回表达式本身是匿名函数的一部分,则在执行返回表达式之前,f的封闭实例可能已经返回.在这种情况下,抛出的scala.runtime.NonLocalReturnException将不会被捕获,并将向上传播调用堆栈.

这是一个NonLocalReturnControl逃逸的例子:

var g: () => Unit = _
def f() { g = () => return }
f() // set g
g() // scala.runtime.NonLocalReturnControl$mcI$sp
Run Code Online (Sandbox Code Playgroud)


Dan*_*ral 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
}
Run Code Online (Sandbox Code Playgroud)