Skip to content

Instantly share code, notes, and snippets.

@kmizu
Created September 24, 2011 08:27
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kmizu/1239117 to your computer and use it in GitHub Desktop.
Save kmizu/1239117 to your computer and use it in GitHub Desktop.
Yet another "generator" library implementation in Scala.
//To compile this, "-P:continuations:enable" option is needed.
import scala.util.continuations._
import scala.collection._
object Generator {
abstract sealed class Computation[+A]
case class Yielded[A](k: Unit => Computation[A], v: A) extends Computation[A]
case object Done extends Computation[Nothing]
type yieldable[A] = cps[Computation[A]]
def make[A](body: (A => Unit @yieldable[A]) => Unit @yieldable[A]): Iterator[A] = new Iterator[A] {
val yields: A => Unit @yieldable[A] = {v =>
shift{k: (Unit => Computation[A]) => Yielded(k, v) }
}
var thunk: Unit => Computation[A] = {x: Unit =>
reset {
body(yields)
Done
}
}
var fetched: Boolean = false
var value: Option[A] = _
def fetch(): Option[A] = {
if(!fetched) {
fetched = true
value = (thunk(()) match {
case Yielded(k, v) =>
thunk = k
Some(v)
case Done =>
None
})
}
value
}
def hasNext(): Boolean = !fetch().isEmpty
def next: A = {
fetch()
fetched = false
value getOrElse (throw new NoSuchElementException("next on empty iterator"))
}
}
}
//To compile this, "-P:continuations:enable" option is needed.
import scala.util.continuations._
import Generator._
object GeneratorUsage {
def main(args: Array[String]) {
val x1 = make[Int]{yields =>
yields(1)
println("X")
yields(2)
println("Y")
yields(3)
}
while(x1.hasNext) {
println("----")
println(x1.next)
}
val x2 = make[Int]{yields =>
var i = 0
while(i < 4){
println("i = " + i)
yields(i)
i += 1
}
}
while(x2.hasNext) {
println("****")
println(x2.next)
}
}
}
# Please see method callings which have side effects in GeneratorUsage.scala
----
1
X
----
2
Y
----
3
i = 0
****
0
i = 1
****
1
i = 2
****
2
i = 3
****
3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment