Skip to content

Instantly share code, notes, and snippets.

@kmizu
Created May 16, 2010 07:52
Show Gist options
  • Save kmizu/402748 to your computer and use it in GitHub Desktop.
Save kmizu/402748 to your computer and use it in GitHub Desktop.
//This file should be compiled unser scala 2.8.0.RC2 with -P:continuations:enable
import scala.util.continuations._
import scala.collection._
trait Generator[+A] extends Traversable[A] {
def moveNext(): Boolean
def current: A
def foreach[U](f: A => U): Unit = {
while(moveNext()) {
f(current)
}
}
}
object Generator {
type susp = cps[Any]
def pass: Unit @susp = shiftUnit0[Unit, Any](())
implicit def unit2cps(u: Unit): Unit @susp = pass
def make[A](body: (A => Unit @susp) => Unit @susp): Generator[A] = new Generator[A] {
val yields: A => Unit @susp = {v =>
shift{k: (Unit => Any) => (k, v):Any }
}
var thunk: Unit => Any = {x: Unit =>
reset {
body(yields)
None
}
}
var value: A = _
def moveNext(): Boolean = {
val result = thunk()
result match {
case (k, v) =>
thunk = k.asInstanceOf[(Unit => Any)]
value = v.asInstanceOf[A]
true
case None =>
false
}
}
def current: A = value
}
}
//This file should be compiled unser scala 2.8.0.RC2 with -P:continuations:enable
import Generator._
/* Existing higher-order functions in the standard library don't handle
* capture of continuations. Then, I implemented such functions.
*/
object Control {
def upto[A](from: Int, to: Int)(f: Int => A @susp): Unit @susp = {
if(from <= to) { f(from); upto(from + 1, to)(f) }
}
def each[A](t: Iterable[A])(f: A => (Unit @susp))
: Unit @susp = {
val it = t.iterator
def loop: Unit @susp = {
if(it.hasNext) {
f(it.next())
loop
}
}
loop
}
}
import Control._
import scala.xml._
object User {
def main(args: Array[String]) {
// Generator which enumerates numbers from 1 to 10
val g1 = make[Int] {yields =>
upto(1, 10) {i =>
yields(i)
}
}
// Generator which enumerates XML elements which are
// descendants of n
def elements(n: Node) = make[Elem]{yields =>
def eachElem(n: Node): Unit @susp = {
n match { case e:Elem => yields(e); case _ => }
each(n.child)(eachElem(_))
}
eachElem(n)
}
val g2 = elements(
<html>
<head>
<title>Scala Delimited Continuation Test</title>
</head>
<body>
<p>Test</p>
</body>
</html>
)
g1.foreach(println)
g2.foreach(e => println(e.label)) //要素名を出力
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment