-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Closed
Labels
Description
Nonlocal returns can have surprising behavior due to the way they interact with try. It turns out that with implicit function types one can delegate non-local returns to a library at basically the same efficiency as what is implemented now.
The idea is to express a non-local return like this:
returning { .... throwReturn(x) .... }
The name throwReturn is chosen so that it is made clear that the return is non-local and involves throwing an exception. The exception is caught at the Returning point where the
transmitted result is returned.
Here's an implementation of this functionality:
package scala.util.control
object NonLocalReturns {
class ReturnThrowable[T] extends ControlThrowable {
private var myResult: T = _
def throwReturn(result: T): Nothing = {
myResult = result
throw this
}
def result: T = myResult
}
def throwReturn[T](result: T)(implicit returner: ReturnThrowable[T]): Nothing =
returner.throwReturn(result)
def returning[T](op: implicit ReturnThrowable[T] => T): T = {
val returner = new ReturnThrowable[T]
try op(returner)
catch {
case ex: ReturnThrowable[_] =>
if (ex `eq` returner) ex.result.asInstanceOf[T] else throw ex
}
}Here's a test case:
def has(xs: List[Int], elem: Int) =
returning {
for (x <- xs)
if (x == elem) throwReturn(true)
false
}Advantages: a simpler language spec and less surprises for the users
Disadvantages: a bit more verbose (which might be a good thing, after all!)
smarter, Daenyth, jducoeur, radusw, ShaneDelmore and 8 moreDavidGregory084, OlivierBlanvillain and sake92