Exception handling around shift in Scala - scala

Scala 2.10.2. Running
import util.continuations._
import concurrent.ops._
object Main {
def main(args: Array[String]) {
reset {
try {
shift { cont: (Unit => Unit) => {
spawn {
throw new Exception("blah")
cont()
}
}}
println("after shift")
} catch {
case e: Exception => println(e)
}
println("reset end")
}
}
}
Gives
Cont.scala:16: error: type mismatch;
found : Unit
required: Unit #scala.util.continuations.cpsParam[Unit,Unit]
case e: Exception => println(e)
^
one error found
If I remove the try/catch block everything's fine. I'm still trying to figure out how continuations work in Scala, but this one totally eludes me.

Just stating the obvious - It is a Scala type inference meets cps-annotation problem. The catch block do not contain any cps annotated expression. In this case the catch-block is expected to be of the same type as the try-block:
Unit #cps[Unit] // same as Unit #cpsParam[Unit,Unit]
To my experience, the type-inference and the CPS-transformation in Scala does not always work as expected and things that work in one version of Scala do not work in another version.
There exists workarounds such as the try_protector mentioned in Scala Continuations - Why can't my shifted call be inside a try-catch block?
Not sure if it helps in your case (i.e. Scala version 2.10.2).

Do you intend the try/catch statement to catch Exception("blah")?
Even if it compiled, spawn which is deprecated would happen on another thread before the flow gets to running the continuation.
Without the try/catch you have something like this:
println("in main " + Thread.currentThread())
reset {
shift { cont: (Unit => Unit) =>
{
spawn {
println("in spawned " + Thread.currentThread())
cont()
}
}
}
println("after shift " + Thread.currentThread())
println("reset end")
}
}
The cont function is the reified portion of code which corresponds to this function:
val cont = () => {
println("after shift " + Thread.currentThread())
println("reset end")
}
So when you do spawn { cont() }, you just run the two println in a new separate thread. Running the program, I get:
in main Thread[main,5,main]
in spawned Thread[Thread-1,5,main]
after shift Thread[Thread-1,5,main]
reset end
That shows that the continuation ran on a separate thread. Now if you insert a throw new Exception() before cont(), then all you get is an exception thrown on the spawned thread (where apparently the exception would be swallowed).
Would running the continuation inside a try/catch and having an exception thrown after the shift be more what you are trying to do?
reset {
shift { cont: (Unit => Unit) =>
spawn {
println("in spawned " + Thread.currentThread())
try { cont() }
catch { case e: Exception => println(e) }
}
}
println("after shift " + Thread.currentThread())
throw new Exception("blah")
println("reset end")
}
}
This prints:
in main Thread[main,5,main]
in spawned Thread[Thread-1,5,main]
after shift Thread[Thread-1,5,main]
java.lang.Exception: blah

Related

If the first statement in a for comprehension fails , recover is not able to catch the exception

I am struggling to understand the for comprehension and exception handling in Scala.
If the first statement in a for comprehension fails , recover is not able to catch the exception.
Code where recover catches the exception successfully(Exception thrown in 2nd statement):
import scala.util.{Success, Try}
object ExceptionThrownIn2ndStatement {
def failTryUnit(x: Unit): Try[Int] = {
println(x)
val a = 1 / 0
new Success(a)
}
def main(args: Array[String]): Unit = {
(for {
var0 <- Try(println("Zeroth function"))
varFailure <- failTryUnit(var0) //exception thrown here
var1 <- Try(println("first function", varFailure))
} yield var1) recover { case e =>
println("Exception caught", e) //exception caught here
}
}
}
Output :
Zeroth function
()
(Exception caught,java.lang.ArithmeticException: / by zero)
Code where recover does NOT catch the exception successfully :
import scala.util.{Success, Try}
object ExceptionThrownIn1stStatement {
def failTryUnit(x: Unit): Try[Int] = {
println(x)
val a = 1 / 0
new Success(a)
}
def main(args: Array[String]): Unit = {
(for {
varFailure <- failTryUnit({}) //exception thrown here
var0 <- Try(println("zeroth function", varFailure))
var1 <- Try(println("first function", var0))
} yield var1) recover { case e =>
println("Exception caught",e) //Exception does not get caught here
}
}
}
Output:
()
Exception in thread "main" java.lang.ArithmeticException: / by zero
at ExceptionThrownIn1stStatement$.failTryUnit(ExceptionThrownIn1stStatement.scala:6)
at ExceptionThrownIn1stStatement$.main(ExceptionThrownIn1stStatement.scala:12)
at ExceptionThrownIn1stStatement.main(ExceptionThrownIn1stStatement.scala)
Edit : I understand that this is not the way recover is supposed to be used.
I am just confused as to why this happens. Please help me understand this. I am new to Scala.
Here is a shorter example that demonstrates the same behavior:
Success(42).flatMap(x => { assert(false); Success(x + 58) })
vs.
{ assert(false); Success(42) }.flatMap(x => Success(x + 58))
The first one will return a Failure with a caught error. The second one will crash with an AssertionError.
The first returns a Failure because that's the semantics of Trys flatMap - it catches all exceptions that occur during the execution of the function passed to it.
The second one crashes immediately, because the very first statement is an assert(false), so you never get to the point where you construct a Try in the first place, the AssertionError is thrown before the first Success constructor is invoked. It wouldn't matter whether you append more recovers on it or not - no Try will ever be instantiated in this program.
Here is what you would have to do to catch the exception occurring during the very first calculation (42):
Try { assert(false); 42 }.flatMap(x => Success(x + 58))
In your code, that would be
def failTryUnit(x: Unit): Try[Int] = Try {
println(x)
1 / 0
}

Exception not caught in map when using a placeholder

I have just come across a quite baffling anomaly in scala. Say I define the following three lines of code:
def f(d: Int): String = throw new RuntimeException("Catch this")
Some(0).map { x => try { f(x) } catch { case ex: Exception => println("Caught first"); "" } }
Some(0).map { try { f(_) } catch { case ex: Exception => println("Caught second"); "" } }
When I run this only "Caught first" gets printed out. It seems that when I use a placeholder in my map function the catch body is never invoked.
Can someone say why this would it be? Could it be a compiler bug? I have tested it with scala 2.11.6
The second version expands to:
Some(0).map { try { x => f(x) } catch { case ex: Exception => println("Caught second"); "" } }
That is, f(_) expands to x => f(x) within the try block, so it remains an unapplied function. The unapplied function will not throw an exception, so the try/catch block returns it and it is used by Option#map where it throws the exception.

How do I get hold of exceptions thrown in a Scala Future?

I've been working up my answer to Is there a standard Scala function for running a block with a timeout?, and have run into a problem if an exception is thrown in a Future.
def runWithTimeout[T](timeoutMs: Long)(f: => T) : Option[T] = {
awaitAll(timeoutMs, future(f)).head.asInstanceOf[Option[T]]
}
So that
runWithTimeout(50) { "result" } should equal (Some("result"))
runWithTimeout(50) { Thread.sleep(100); "result" } should equal (None)
But if I throw an exception in my block it doesn't leak, but is swallowed - so that the following fails with "..no exception was thrown"
intercept[Exception] {
runWithTimeout(50) { throw new Exception("deliberate") }
}.getMessage should equal("deliberate")
Syserr has a stack trace with the message
<function0>: caught java.lang.Exception: deliberate
but I can't find where in the Scala runtime that is printed.
Apart from wrapping f in another block which catches exceptions and propagates them if thrown, is there any way to persuade awaitAll and/or Future to throw?
Short answer: no.
Exceptions don't do what you want when you're working in a threaded context, because you want to know about the exception in the caller, and the exception happens in the future's thread.
Instead, if you want to know what the exception was, you should return an Either[Exception,WhatYouWant]--of course, you have to catch that exception within the future and package it up.
scala> scala.actors.Futures.future{
try { Right("fail".toInt) } catch { case e: Exception => Left(e) }
}
res0: scala.actors.Future[Product with Serializable with Either[Exception,Int]] = <function0>
scala> res0() // Apply the future
res1: Product with Serializable with Either[Exception,Int] =
Left(java.lang.NumberFormatException: For input string: "fail")
Disclaimer: I work for Typesafe
Or.... you could use Akka and it would give you what you want without you having to go through hoops for it.
val f: Future[Int] = actor !!! message
Then
f.get
Will throw the exception that happened in the actor
f.await.exception
will give you an Option[Throwable]
Working my way through #Rex Kerr's suggestion, I've created
object Timeout {
val timeoutException = new TimeoutException
def runWithTimeout[T](timeoutMs: Long)(f: => T) : Either[Throwable, T] = {
runWithTimeoutIgnoreExceptions(timeoutMs)(exceptionOrResult(f)) match {
case Some(x) => x
case None => Left(timeoutException)
}
}
def runWithTimeout[T](timeoutMs: Long, default: T)(f: => T) : Either[Throwable, T] = {
val defaultAsEither: Either[Throwable, T] = Right(default)
runWithTimeoutIgnoreExceptions(timeoutMs, defaultAsEither)(exceptionOrResult(f))
}
def runWithTimeoutIgnoreExceptions[T](timeoutMs: Long)(f: => T) : Option[T] = {
awaitAll(timeoutMs, future(f)).head.asInstanceOf[Option[T]]
}
def runWithTimeoutIgnoreExceptions[T](timeoutMs: Long, default: T)(f: => T) : T = {
runWithTimeoutIgnoreExceptions(timeoutMs)(f).getOrElse(default)
}
private def exceptionOrResult[T](f: => T): Either[Throwable, T] =
try {
Right(f)
} catch {
case x => Left(x)
}
}
so that
#Test def test_exception {
runWithTimeout(50) { "result" }.right.get should be ("result")
runWithTimeout(50) { throw new Exception("deliberate") }.left.get.getMessage should be ("deliberate")
runWithTimeout(50) { Thread.sleep(100); "result" }.left.get should be (Timeout.timeoutException)
runWithTimeout(50, "no result") { "result" }.right.get should be ("result")
runWithTimeout(50, "no result") { throw new Exception("deliberate") }.left.get.getMessage should be ("deliberate")
runWithTimeout(50, "no result") { Thread.sleep(100); "result" }.right.get should be ("no result")
}
Again, I'm a bit of a Scala novice, so would welcome feedback.
scala.concurrent.ops.future includes exception handling.
So, instead of importing scala.actors.Futures.future, import scala.concurrent.ops.future instead.
That simple change in which import is there will cause the caller's call to .get to rethrow the exception. It works great!
Or use Future.liftTryTry, turns it from Future[Object] to Future[Try[Object]], and you can match on the Try[Object] and check for an exception case Throw(e) and log / exit gracefully
You need to override the method exceptionHandler in order to catch exceptions. So your option is to define your own future method so it creates a MyFutureActor with exceptionHandler.
EDIT: FutureActor is private, so subclassing it isn't possible.
Another option is to use links to know when exceptions happened.
However, I think Rex Kerr's approach is better - just wrap the function in something that will catch the Exception. Too bad future doesn't already do that.

How to catch an exception within loop/react of an actor?

Is it possible to catch an exception raised within behaviour? Where to place the try/catch? I know that react uses exceptions to reuse the same thread for different actors and that´s why I don´t know where to put the try/catch. I want to catch certain exceptions by myself for logging.
import scala.actors._
def behaviour: PartialFunction[Any,Unit] = {
case x =>
println(x)
throw new IllegalStateException
}
val a = new Actor {
def act {
loop {
react {
behaviour
}
}
}
}
a.start
a ! "Bam"
eThe Actor has a exception handler function which can be overridden:
override def exceptionHandler = {
case e: Exception =>
println(e.getMessage())
}
Whenever a exception is raised in the actor that would normally cause it to terminate - the exceptionHandler partial function is applied to the exception.
Edit
With Exception filter:
class ExceptionalActor extends Actor{
def act() {
loop {
react {
case "bad" => throw new NoSuchFieldException("Bad Message")
case "impossible" => throw new Exception("Impossible Exception")
case m => println("non-bad message " + m )
}
}
}
override def exceptionHandler = {
case e: NoSuchFieldException => println("handled " + e.getMessage() )
}
}
object Tester extends App {
val eActr = new ExceptionalActor
eActr start
eActr ! "any message1"
eActr ! "bad"
eActr ! "any message2"
eActr ! "impossible"
eActr ! "any message3"
}
produces:
non-bad message any message1
handled Bad Message
non-bad message any message2
org.scratch.act.ExceptionalActor#7f5663a2: caught java.lang.Exception: Impossible Exception
:
And actor death.
ref: Actors in Scala

Better syntax for Scala anonymous function?

Experimenting with Scala... I'm trying to define something analogous to the "#" hack in PHP (which means, ignore any exception in the following statement).
I managed to get a definition that works:
def ignoreException(f: () => Unit) = {
try {
f();
}
catch {
case e: Exception => println("exception ignored: " + e);
}
}
And use it like this:
ignoreException( () => { someExceptionThrowingCodeHere() } );
Now here is my question... Is there anyway I can simplify the usage and get rid of the () =>, and maybe even the brackets?
Ultimately I'd like the usage to be something like this:
`#` { someExceptionThrowingCodeHere(); }
# is reserved in Scala (for pattern matching), but would you accept ##?
scala> def ##(block: => Unit): Unit = try {
block
} catch {
case e => printf("Exception ignored: %s%n", e)
}
$at$at: (=> Unit)Unit
scala> ## {
println("before exception")
throw new RuntimeException()
println("after exception")
}
before exception
Exception ignored: java.lang.RuntimeException
I'm not convinced this is a good idea, however ☺
You don't have to use a function as your parameter, a "by-name" parameter will do:
def ignoreException(f: =>Unit) = {
try {
f
}
catch {
case e: Exception => println("exception ignored: " + e)
}
}
ignoreException(someExceptionThrowingCodeHere())
Eric.