Better syntax for Scala anonymous function? - scala

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.

Related

Scala "Try" return type and exception handling

I am a newbie for Scala and now am trying to complete an exercise. How can I return an InvalidCartException while the function return type is Try[Price]
//Success: return the calculated price
//Failure: InvalidCartException
def calculateCartPrice(cart:Cart): Try[Price] = {
if(isCartValid(cart)) {
//Calculations happen here
return Try(Price(totalPrice));
}
}
def isCartValid(cart: Cart): Boolean = {
//THIS WORKS FINE
}
Thank you for the help
If you mean "how to make the Try contain an exception", then use the Failure() like below:
def calculateCartPrice(cart:Cart): Try[Price] = {
if(isCartValid(cart)) {
//Calculations happen here
Success(Price(totalPrice));
} else {
Failure(new InvalidCartException())
}
}
Then, given a Try you can use getOrElse to get the value of success or throw the exception.
Try will catch the exception for you, so put the code that can throw the exception in there. For example
def divideOneBy(x: Int): Try[Int] = Try { 1 / x}
divideOneBy(0) // Failure(java.lang.ArithmeticException: / by zero)
If what you have is a Try and you want to throw the exception when you have a Failure, then you can use pattern matching to do that:
val result = divideByOne(0)
result match {
case Failure(exception) => throw exception
case Success(_) => // What happens here?
}
The Neophyte's Guide to Scala has lots of useful information for people new to Scala (I found it invaluable when I was learning).

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 to use StaticQuery in Slick 3.0.0?

In Slick 2.1 I had the code below to execute an sql-query from a file:
def fetchResult[T](sql: String)(implicit getResult: GetResult[T]): List[T] = {
val query = Q.queryNA[T](sql)
try {
Database.forDataSource(DB.getDataSource())
.withSession { implicit session => query.list }
}
catch {
case e: Throwable =>
throw new RunSqlException(s"Query $name execution error", e)
}
}
In Slick 3.0.0 you use dbConfig.db.run method to execute DBIOAction and get a future of the result. But I can't find a way to transform result of Q.queryNA (which is StaticQuery[Unit, R]) into DBIOAction. Does such a way exist?
I ended up with deprecated calls for now. Help me be better!
def fetchResult[T](sql: String)(implicit getResult: GetResult[T]): Future[List[T]] = Future {
val query = Q.queryNA[T](sql)
try {
this.dbConfig.db.withSession { implicit session => query.list }
}
catch {
case e: Throwable =>
throw new RunSqlException(s"Query $name execution error", e)
}
}
Only solution I managed to find was a bit hackish:
import slick.driver.HsqldbDriver.api._
def fetchResult[T](sql: String) = {
database.run(sqlu"""#$sql""")
}

Matching on nested exception type

I am using some client library and had some code that ignored a specific exception using scala.util.control.Exception.ignoring:
ignoring(classOf[ReallyNotThatExceptionalException]) {
stuff()
}
Now that library changed to wrap all exceptionn in another exception class, which forced me to change my code to this:
try { stuff() }
catch {
case e:WrapperException if e.getCause != null && e.getCause.isInstanceOf[ReallyNotThatExceptionalException] => { }
}
So what I'm looking for a more readable way to express "catch exceptions that are caused by".
0__'s answer is good, but it would be better if you were not forced to write a specific object (CausedByFoo) for each potential exception.
As it happens, there is not much to change to end up with a generic CausedBy helper object:
class Foo(message: String) extends Exception(message)
class Bar(cause: Throwable) extends Exception(cause)
object CausedBy {
def unapply(e: Throwable): Option[Throwable] = Option(e.getCause)
}
def test(block: => Unit): String =
try {
block
"ok"
} catch {
case CausedBy(ex: Foo) => "not ok: " + ex.getMessage
}
test(println("hello"))
test(println("hello".toInt)) // uncaught exception
test(throw new Bar(new Foo("Ooops, foo error!"))) // caught
As should be obvious, you can use CausedBy with any exception (by example by doing case CausedBy(ex: Baz).
You can even nest it to handle an exception caused by an exception caused by an exception (by doing something like case CausedBy(CausedBy(ex: Foo))
The catch block can handle any regular pattern match, so
class Foo extends Exception
class Bar(cause: Exception) extends Exception(cause)
object CausedByFoo {
def unapply(e: Exception): Boolean = e.getCause match {
case _: Foo => true
case _ => false
}
}
def test(block: => Unit): String =
try {
block
"ok"
} catch {
case CausedByFoo() => "not ok"
}
test(println("hello"))
test(println("hello".toInt)) // uncaught exception
test(throw new Bar(new Foo)) // caught
I tweaked Régis' answer to allow matching against both outer and inner exception type.
trait CausedBy[T <: Throwable] {
def unapply(e: T): Option[Throwable] = Option(e.getCause)
}
object IOExceptionCausedBy extends CausedBy[IOException]
Then you can match like this:
try {
// do some DB thing
} catch {
case IOExceptionCausedBy(exception: PSQLException) =>
// handle PSQL 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.