Skip to content

Instantly share code, notes, and snippets.

@shomah4a
Forked from anonymous/generator.scala
Created January 14, 2011 14:00
Show Gist options
  • Save shomah4a/779633 to your computer and use it in GitHub Desktop.
Save shomah4a/779633 to your computer and use it in GitHub Desktop.
package net.shomah4a.utils.generator.continuation
import scala.util.continuations.{reset, shift, cpsParam}
object Generator
{
type GenParam[T] = (Option[T], Option[GeneratorSupport[T]])
type GenState[T] = cpsParam[GenParam[T], GenParam[T]]
def gen[T](f: => Unit@GenState[T]) = new Generator[T](f)
def yld[T](v: T):Unit@GenState[T] =
{
def cont(ctx: (Unit => GenParam[T])): GenParam[T] =
{
(Some(v), Some(new GeneratorSupport[T]({ctx()}))).asInstanceOf[GenParam[T]]
}
shift[Unit, GenParam[T], GenParam[T]](cont)
}
implicit def iterableToContIterator[T](it: Iterable[T]) = new ContIterable(it)
}
class ContIterable[T](iterable: Iterable[T])
{
def foreachM(f: (T => Unit@Generator.GenState[T])): Unit@Generator.GenState[T] =
{
val it = iterable.toIterator
while (it.hasNext)
{
f(it.next)
}
}
val mapM_ = foreachM _
}
class GeneratorSupport[T](f: => Generator.GenParam[T])
{
def apply() = f
}
class Generator[T](f: => Unit@Generator.GenState[T]) extends Iterator[T]
{
var value: Option[T] = None
var context: Option[GeneratorSupport[T]] = None
{
val x:Generator.GenParam[T] = reset {
f
(None, None):Generator.GenParam[T]
}
this.value = x._1
this.context = x._2
}
def hasNext() =
{
this.context != None
}
def next() =
{
val prev = this.value.get
val (v, ctx) = (this.context.get)()
this.value = v
this.context = ctx
prev
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment