Skip to content

Commit 70e3537

Browse files
Add library replacement to nonlocal returns
1 parent 54cfe6a commit 70e3537

File tree

2 files changed

+50
-0
lines changed

2 files changed

+50
-0
lines changed
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package scala.util.control
2+
3+
/** Library implementation of nonlocal return.
4+
*
5+
* Usage:
6+
*
7+
* import scala.util.control.NonLocalReturns._
8+
*
9+
* returning { ... throwReturn(x) ... }
10+
*/
11+
object NonLocalReturns {
12+
class ReturnThrowable[T] extends ControlThrowable {
13+
private var myResult: T = _
14+
def throwReturn(result: T): Nothing = {
15+
myResult = result
16+
throw this
17+
}
18+
def result: T = myResult
19+
}
20+
21+
/** Performs a nonlocal return by throwing an exception. */
22+
def throwReturn[T](result: T) given (returner: ReturnThrowable[T]): Nothing =
23+
returner.throwReturn(result)
24+
25+
/** Enable nonlocal returns in `op`. */
26+
def returning[T](op: given ReturnThrowable[T] => T): T = {
27+
val returner = new ReturnThrowable[T]
28+
try op given returner
29+
catch {
30+
case ex: ReturnThrowable[T] =>
31+
if (ex.eq(returner)) ex.result else throw ex
32+
}
33+
}
34+
}

tests/run/nonlocal-return.scala

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import scala.util.control.NonLocalReturns._
2+
3+
object Test {
4+
def has(xs: List[Int], elem: Int) =
5+
returning {
6+
for (x <- xs)
7+
if (x == elem) throwReturn(true)
8+
false
9+
}
10+
11+
def main(arg: Array[String]): Unit = {
12+
assert(has(1 :: 2 :: Nil, 1))
13+
assert(has(1 :: 2 :: Nil, 2))
14+
assert(!has(1 :: 2 :: Nil, 3))
15+
}
16+
}

0 commit comments

Comments
 (0)