Suppose, I would like to catch an exception, fix the problem caused the exception and return to the same execution point where the exception occurred to continue.
How ca
Here is one of the possible ways of implementing resumable error handling:
import java.io.File
import java.lang.IllegalStateException
import scala.util.continuations._
// how it works
ctry {
println("start")
val operationResult = someOperation(new File("c:\\ttttest"))
println("end " + operationResult)
} ccatch {
case (DirNotExists(dir), resume) =>
println("Handling error")
dir.mkdirs()
resume()
}
def someOperation(dir: File) = {
cthrow(DirNotExists(dir))
println(dir.getAbsolutePath + " " + dir.exists)
"Operation finished"
}
// exceptions
trait CException
case class DirNotExists(file: File) extends CException
// ctry/ccatch classes and methods
sealed trait CTryResult[T] {
def get: T
def ccatch(fn: PartialFunction[(CException, () => T), T]): T
}
case class COk[T](value: T) extends CTryResult[T] {
def ccatch(fn: PartialFunction[(CException, () => T), T]) = value
def get = value
}
case class CProblem[T](e: CException, k: Any => Any) extends CTryResult[T] {
def ccatch(fn: PartialFunction[(CException, () => T), T]) =
fn((e, () => k(Unit).asInstanceOf[T]))
def get = throw new IllegalStateException("Exception was not processed: " + e)
}
def ctry[T](body: => T @cps[Any]) = reset (body) match {
case (e: CException, k: (Any => Any)) => CProblem[T](e, k)
case value => COk(value)
}
def cthrow(e: CException): Any @cps[Any] = shift((k: Any => Any) => (e, k))
This code produces following output:
start
Handling error
c:\ttttest true
end Operation finished