import scala.util.continuations.cpsParam
import scala.util.continuations.reset
import scala.util.continuations.shift
import scala.collection.mutable.Stack
private val ks: Stack[HasEnv with HasReadLn with HasWrite => Unit] =
Stack.empty[HasEnv with HasReadLn with HasWrite => Unit]
trait HasEnv {
def env: Map[String, String]
}
def readEnv(name: String): String@cpsParam[Unit, Unit] =
{ (k: String => Unit) =>
shift .push({ r: HasEnv => k(r.env(name)) })
ks()
}
trait HasReadLn {
def readLn(): String
}
def readLn(): String@cpsParam[Unit, Unit] =
{ (k: String => Unit) =>
shift .push({ r: HasReadLn => k(r.readLn()) })
ks()
}
trait HasWrite {
def write(output: String): Unit
}
def write(output: String): Unit@cpsParam[Unit, Unit] =
{ (k: Unit => Unit) =>
shift .push({ r: HasWrite =>
ks.write(output)
rk()
})
()
}
def enProgram(): Unit@cpsParam[Unit, Unit] = {
write("What's your name? ")
val name: String = readLn()
write(s"Hello, ${name}!\n")
}
def esProgram(): Unit@cpsParam[Unit, Unit] = {
write("¿Cómo te llamas? ")
val name: String = readLn()
write(s"¡Hola, ${name}!\n")
}
def program(): Unit@cpsParam[Unit, Unit] = {
val lang: String = readEnv("LANG")
if (lang.startsWith("es")) {
esProgram()
} else {
enProgram()
}
}
val r: HasEnv with HasReadLn with HasWrite =
new HasEnv with HasReadLn with HasWrite {
override val env: Map[String, String] = sys.env
override def readLn(): String = scala.io.StdIn.readLine()
override def write(output: String): Unit = print(output)
}
{
reset program()
}
while (ks.nonEmpty) {
val k: HasEnv with HasReadLn with HasWrite => Unit = ks.pop()
k(r)
}
See the compiler plugin support section of the sbt documentation for the latest configuration information.
For sbt 1.0 and Scala 2.12, use the following:
/***
:= "2.12.2"
scalaVersion
( "org.scala-lang.plugins"
addCompilerPlugin% "scala-continuations-plugin_2.12.2"
% "1.0.3"
)
+=
libraryDependencies "org.scala-lang.plugins" %% "scala-continuations-library" % "1.0.3"
+= "-P:continuations:enable"
scalacOptions */
This file is literate Scala, and can be run using Codedown:
$ curl https://earldouglas.com/posts/effect-systems/cps.md |
codedown scala > script.scala
$ LANG=es sbt -Dsbt.main.class=sbt.ScriptMain script.scala
¿Cómo te llamas? James
¡Hola, James!