The semantics are relatively simple: return
will throw a NonLocalReturnControl
that is caught at the enclosing method, toUpper
. It doesn't look like a recent feature; there is no mention of return
in the Scala change-log since version 2.0.
Here's the relevant description from the Scala Language Spec, section 6.20:
Returning from a nested anonymous function is implemented by throwing
and catching a scala.runtime.NonLocalReturnException. Any exception
catches between the point of return and the enclosing methods might
see the exception. A key comparison makes sure that these exceptions
are only caught by the method instance which is terminated by the return.
If the return expression is itself part of an anonymous function, it
is possible that the enclosing instance of f has already returned
before the return expression is executed. In that case, the thrown
scala.runtime.NonLocalReturnException will not be caught, and will
propagate up the call stack.
Here's an example in which the NonLocalReturnControl
escapes:
var g: () => Unit = _
def f() { g = () => return }
f() // set g
g() // scala.runtime.NonLocalReturnControl$mcI$sp