bangnotation

Example

Suppose you are generating a random integer less than 100, whose first digit and second digit is different. A solution is generating integers in an infinite loop, and Return from the loop when the generated integer conforms with requirements.

import scala.util.Random
import scala.util.control.TailCalls
import scala.util.control.TailCalls.TailRec
import com.thoughtworks.dsl.bangnotation.reset
def randomInt(): TailRec[Int] = reset {
 while (true) {
   val r = Random.nextInt(100)
   if (r % 10 != r / 10) {
     !Return(TailCalls.done(r))
   }
 }
 throw new AssertionError("Unreachable code");
}
val r = randomInt().result
r should be < 100
r % 10 should not be r / 10

Since the Return keyword can automatically lift the return type, TailCalls.done can be omitted.

import scala.util.Random
import scala.util.control.TailCalls
import scala.util.control.TailCalls.TailRec
def randomInt(): TailRec[Int] = reset {
 while (true) {
   val r = Random.nextInt(100)
   if (r % 10 != r / 10) {
     !Return(r)
   }
 }
 throw new AssertionError("Unreachable code");
}
val r = randomInt().result
r should be < 100
r % 10 should not be r / 10
class Object
trait Matchable
class Any

Type members

Classlikes

class *[Functor[_]]
object Macros

Value members

Concrete methods

inline
def *[Domain[_]]: *[Domain]
transparent inline
def reify[Value](inline value: Value): Any
inline
def reset[Value](inline value: Value): Value

Extensions

Extensions

extension [Keyword, Value](keyword: Keyword)
@compileTimeOnly("This method must be called only inside a `reset` or `*` code block.")
def unary_!(using IsKeyword[Keyword, Value]): Value