Exception not caught in map when using a placeholder - scala

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.

Related

How to "override" an exception in scala?

so I have a method which already has a try block that throws ExceptionA. Now I need to put another try block where this method is being called and needs to throw an exception with some added details. Something like this:
method inner():
try{
//some logic
} catch {
throw new ExceptionA("exceptionA occurred")
}
method outer():
identifier = fromSomeDBCallPrivateToOuter()
try{
inner()
} catch {
// now either
// throw new Exception("Error with identifier" + identifier)
// or
// append identifier to thrown error from inner()
}
Can someone please provide any insight or suggestion on how to do this in Scala? Thanks in advance!
What you have in your snippet would work as written (if you correct the syntax), with a caveat, that exceptions are immutable (and even they weren't, it's still not a good idea to mutate them), so, instead of "appending" to exception, you'd need to create a new one, and set the original as cause.
It is more idiomatic in scala though to use Try monad instead of the "procedural" try/catch blocks. Something like this:
case class ExceptionB(id: String, original: ExceptionA)
extends Exception(s"Badness happened with id $id", original)
def outer(): Try[ReturnType] =
val id = getId()
Try {
inner
} recover {
case e: ExceptionA if iWannaNewException => throw new Exception(s"Id: id")
case e: ExceptionA => throw ExceptionB(id, e)
}
You can also use Either structure. This structure can return Right(value) if function completes without error or Left(message) containing information about error. You can adapt your code like below one:
def inner(): Either[String, Int] = {
if (checkSomeStuff()) Left("Cannot assigne identifier")
else Right(doSomeStuff())
}
def outer(): Either[String, Int] = {
inner() match {
case Left(error) => {
println("There is an error: " + error)
// you can also throw new Exception(s"Some info about $error") here
}
case Right(identifier) => {
println("Identifier : " + identifier)
doSomeStuffWithId() // do some staff for id
}
}
}
If you want to use Exceptions you need to choose who will handle the error case (in the inner or in the outer function).

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).

Code runs with fastOptJS but fails with fullOptJS in Scala.js

I'm catching an UndefinedBehaviorError thrown by the bad asInstanceOf in my code like this:
$("button").on(
"click",
".showDialog",
(event: JQueryEventObject) => {
event.preventDefault()
val helpText = "Enter any number"
js.Dynamic.global.swal(
JC(
title = helpText,
text = helpText,
`type` = "input",
showCancelButton = true,
closeOnConfirm = false,
inputPlaceholder = helpText
),
(input: Any) => {
try {
input.asInstanceOf[Boolean]
} catch {
case _: Throwable =>
try {
val correctInput = input.asInstanceOf[String].toDouble
global.console.log("success")
} catch {
case _: Throwable =>
js.Dynamic.global.swal.showInputError("Incorrect data!")
}
}
}
)
}
)
It works fine with fastOptJS but fails with fullOptJS. How to correctly rewrite this code to run it with fullOptJS or what are the other options?
In Scala.js, a bad cast does not reliably throw a ClassCastException, unlike in Scala/JVM. Instead, a bad cast is an undefined behavior, as specified here. This means that in fullOpt, the program can behave arbitrarily, and in particular is allowed not in throw. In fastOpt, however, the compiler is kind and reliably throws, but not a ClassCastException (as it would give a false sense of security), rather an UndefinedBehaviorError.
UndefinedBehaviorErrors must never be caught, as catching one hides a bug which will surface in fullOpt. This is your mistake here: you are catching that UndefinedBehaviorError under case _: Throwable =>. Note that catching Throwable is bad practice in Scala. Instead, you should be using case scala.util.control.NonFatal(_) =>. A NonFatal handler does not catch UndefinedBehaviorError, and would therefore not hide the bug.
Now to solve your issue, you simply not use asInstanceOf as a means to type-test. Even on Scala/JVM, that code would be super bad practice. Use pattern matching instead:
(input: Any) => {
def reportIncorrectData(): Unit =
js.Dynamic.global.swal.showInputError("Incorrect data!")
input match {
case input: Boolean =>
// Here, input is a Boolean
input
case input: String =>
// Here, it is a String; let's try to convert it to Double
try {
val correctInput = input.toDouble
} catch {
case _: NumberFormatException =>
reportIncorrectData()
}
case _ =>
// It is something else, always incorrect data
reportIncorrectData()
}
}

Scala Continuations - Why can't my shifted call be inside a try-catch block?

I'm new to Scala continuations, and relatively new to the scala language in general.
I tried playing with Scala continuations and wrote the following code:
case class MyException(msg:String) extends Exception
def go:Int = reset {
println("enter your input")
val my_check = //try
{
val user_input = readLine()
if (!user_input.matches("\\w+")) {
throw new MyException("illegal string: " + user_input)
}
shift {
k: (Boolean => Int) => {
if (user_input == "true") {
k(true)
}
else if (user_input == "false") {
k(false)
}
else {
// don't even continue
0
}
}
}
}
// catch {
// case MyException(msg) => false
// }
if (my_check) {
println("TRUE")
1
}
else {
println("FALSE")
-1
}
}
println(go)
The code worked as expected: when the user enters a non-alphanumeric string a MyException is thrown, when the user enters "true" the code continues with my_check = true, when the user enters "false" the code continues with my_check = false, and when the user enters an alphanumeric string which is not "true" nor "false" the go function exits with 0.
Then I tried wrapping some of the code in a try-catch block (where the comments are), and the compilation failed with:
error: found cps expression in non-cps position
val my_check = try
I understand there's a problem with "injecting" an exception into a continuation, but why can't I simply put the shifted call inside a try-catch block?
I need this in the framework I'm planning, in which the programmer will not be aware that his code is used in a continuation form (he'll call some function which he would think to be "normal", but will actually do the shift).
Obviously, I need him to be able to call the function inside a try-catch block, even though the shifted call itself will not raise an exception.
Can this issue be solved with ControlContext?
Will it help if I add some "typing" rules on the values (maybe with the #cps[..])?
I already thought about the alternative of using Actors so you won't get any credit for that :)
Thanks,
(P.S. I'm using Scala 2.9.2, and obviously use the -P:continuations:enable flag)
Thanks #som-snytt, but your solution was somewhat far from a generic one. I can't demand the framework user to write def my_check instead of val my_check every time it uses a try-catch block.
However, I played with your solution, and built the following code:
import scala.util.continuations._
case class MyException(msg:String) extends Exception
object try_protector {
def apply[A,B](comp: => A #cps[B]):A #cps[B] = {
comp
}
}
object Test extends App {
def go: Int = reset {
println("enter your input")
val my_check = try_protector {
try {
val user_input = readLine()
if (!user_input.matches("\\w+")) {
throw new MyException("illegal string: " + user_input)
}
shift {
k: (Boolean => Int) => {
user_input match {
case "true" => k(true)
case "false" => k(false)
case _ => 0
}
}
}
} catch {
case MyException(msg) => false
}
}
if (my_check) {
println("TRUE")
1
} else {
println("FALSE")
-1
}
}
println(go)
}
And it works! (on scala 2.9.2)
The user just has to wrap his try-catch block with a try_protector and the code will compile.
Don't ask me how or why... It looks like compilation VODOU to me...
I haven't tried it on scala 2.10.

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.