Loops
Effekt includes a (almost standard) built-in while
loop expression as its sole native looping construct.
def fib(n: Int): Int = {
var last = 0
var current = 1
var iters = 0
while (iters < n) {
val next = last + current
last = current
current = next
iters = iters + 1
} else { println("ran for " ++ show(iters) ++ " iterations") }
last
}
fib(10)
A while
loop consists of a condition on which to continue the loop, the body, and an optional else
branch that is run when the
while
loop ended.
Furthermore, there is a loop
function defined in the standard library, you can use for infinite, breakable loops.
interface Event[A] {
def receive(): Option[A]
}
record Job()
def worker() = loop { {l} =>
val packet = do receive[Job]()
packet match {
case Some(p) => println("processing request")
case None() => l.break()
}
}
The operations break
and continue
have their usual semantics, except that they are handled by loop
as operations of the algebraic effect Control
.
Additionally, the standard library also includes the functions each
and repeat
.
each(1, 11) { (n) => if (n.mod(2) == 0) println(n) }
each
expects two value arguments: an inclusive starting index and an exclusive end index. At each iteration, the current index is passed to the block argument of each
.
You may also use the operations break
and continue
when binding a label (here l
):
each(1, 11) { (n) {l} => if (n.mod(2) == 0) println(n) else l.continue() }
repeat
just expects one value argument that controls how often the passed block argument is to be executed. Again, you may bind a label to use the operations of the Control
effect here.
repeat(2) { println("Effekt!") }