Является ли нелокальное возвращение в Scala новым? - PullRequest
24 голосов
/ 02 августа 2011

Коллега только что показал мне это, и я был удивлен, что это скомпилировано:

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 изнутри закрытие не было разрешено. С каких пор это сработало? Есть ли предостережения с такими нелокальными доходами?

Ответы [ 2 ]

24 голосов
/ 02 августа 2011

Семантика относительно проста: return сгенерирует NonLocalReturnControl, который пойман при включающем методе toUpper. Это не похоже на недавнюю особенность; в журнале изменений Scala нет упоминания return, начиная с версии 2.0.

Вот соответствующее описание из спецификации языка 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
6 голосов
/ 03 августа 2011

Это разрешено с незапамятных времен, более или менее.Там это может выглядеть странно, но есть много мест, где обратное будет правдой.Например:

// 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
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...