-
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