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将抛出一个NonLocalReturnControl被封闭方法捕获的toUpper. 它看起来不像是最近的功能。自 2.0 版以来returnScala 更改日志中没有提及。

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

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

如果 return 表达式本身是匿名函数的一部分,则 f 的封闭实例可能在 return 表达式执行之前已经返回。在这种情况下,抛出的 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 回答