In which cases does try-catch catch exceptions? - scala

I've just started learning Scala, so this might be a simple question. I want to use a try-catch block to check if a variable has been declared or not.
I am using a try-catch block and catching the NoSuchElementException if the variable doesn't exist.
try{
print(testVariable)
}
catch{
case e: NoSuchElementException => print("testVariable not found")
}
My code is showing an error that testVariable does not exist instead of throwing the exception. I then tried multiple other exceptions as well, but Scala's try-catch doesn't seem to be catching any of them (except for the divide by zero exception).
Can someone please guide me on how to use Scala's try-catch block?

In Scala (or pretty much any compiled programming language really), checking if a variable has been declared or not is the compiler's job, done at compile time. If you try to use a variable that hasn't been declared, the compiler will give an error, and your code won't be able to run.
Exceptions are a way to represent problems at run-time.
There is no overlap between "compile time" and "run-time", so what you are trying to do doesn't make sense. There just isn't an exception for "variable does not exist", and that's why you can't catch it.
To contrast, take this example:
val map = Map('a' -> 1, 'b' -> 2)
map('c') // will throw NoSuchElementException because there is no 'c' in the map
In this case, map.apply('c') (syntax sugar for apply lets you do map('c') will throw an exception because that's how Map's apply method is implemented. See the definition of Map#apply which calls Map#default if the key wasn't in the map; Map#default throws a NoSuchElementException.
You could catch that exception with a try/catch, e.g.
try {
map('c')
} catch {
case e: NoSuchElementException =>
println("got it!")
}

Related

Why does Dart allow arbitrary types to be thrown as exceptions?

In the Dart docs at https://dart.dev/guides/language/language-tour#exceptions, it states the following:
Dart provides Exception and Error types, as well as numerous predefined subtypes. You can, of course, define your own exceptions. However, Dart programs can throw any non-null object—not just Exception and Error objects—as an exception.
The example they give for this behavior is throw 'Out of llamas!';.
Why would I ever want to throw something that isn't an Error or Exception? What is the design decision behind allowing this?
I think it is because you may already have an object that you want to inspect if an error occurs, and can just throw that object, or just so you can throw a string like in the example.
It's worth noting that a catch block can optionally catch the stack trace, and since the stack trace is not part of the Exception, it makes sense to allow arbitrary objects to be thrown.
try {
throw 'Error!';
} catch (error, stacktrace) {
print(stacktrace);
}
Many times you will just see catch (e) in code, but you may also see catch (e, s).

Scala: what are the guarantees of the catch Throwable?

I would like to know the guarantees of the following pattern:
try {
//business logic here
} catch {
case t: Throwable =>
//try to signal the error
//shutdown the app
}
I'm interested in catching all unexpected exceptions (that can be thrown by any framework, library, custom code etc...), trying to record the error and shutting down the virtual machine.
In Scala what are the guarantees of the catch Throwable exception? Are there any differences with the java Exception hierarchy to take in consideration?
Throwable is defined in the JVM spec:
An exception in the Java Virtual Machine is represented by an instance of the class Throwable or one of its subclasses.
which means that both Scala and Java share the same definition of Throwable. In fact, scala.Throwable is just an alias for java.lang.Throwable. So in Scala, a catch clause that handles Throwable will catch all exceptions (and errors) thrown by the enclosed code, just like in Java.
There are any difference with the java Exception hierarchy to take in consideration?
Since Scala uses the same Throwable as Java, Exception and Errors represent the same things. The only "difference" (that I know of) is that in Scala, exceptions are sometimes used under the hood for flow control, so that if you want to catch non-fatal exceptions (thus excluding Errors), you should rather use catch NonFatal(e) instead of catch e : Exception. But this doesn't apply to catching Throwable directly
All harmless Throwables can be caught by:
try {
// dangerous
} catch {
case NonFatal(e) => log.error(e, "Something not that bad.")
}
This way, you never catch an exception that a reasonable application should not try to catch.

analogous Try block to try/finally block in scala

What is the analogous in manners of scala Try to:
timer.start()
try {
doThis()
} finally {
timer.cancel()
}
Given that an exception inside a Try simply creates a Failure value (as opposed to transferring control to an outer catch block when using try), the code in your original finally block would just need to be executed after the Try.
In other words, this will do:
timer.start()
val result = Try{
doThis()
}
timer.cancel()
result
As far as I know there is no built-in shortcut that would allow to avoid capturing result just to return it as is.
Since Try won't throw an exception in your program flow I believe just write the following:
timer.start()
Try(doThis())
timer.cancel()
You can assign Try(doThis()) to a value and process it further if you wish to process the exception (rather than blindly ignoring it) or the call result.
How about
Try {
scala.util.control.Exception.ultimately {
timer.cancel()
} {
doThis()
}
}
?
Despite other answers saying otherwise, the correct answer is a Try cannot be completely analogous to a traditional try...finally. The reason for this is Try will ignore certain types of exceptions including InterruptedException, ControlThrowable, and others.
Consider if you use Try as recommended by other answers:
lock.lock()
val t = Try(doStuff()) // Doesn't absorb all types of exceptions!
lock.unlock() // THIS MIGHT BE SKIPPED!!!
t.get
If the thread is interrupted during doStuff(), then an InterruptedException will be thrown, and Try will rethrow it instead of creating a Failure! This will cause lock.unlock() to be skipped (and you'll probably deadlock). The same will happen if doStuff() invokes a lambda that invokes a non-local return (which throws a sub-type of ControlThrowable).
This is likely why the standard Scala library does not include a finally method in the Try class -- because it wouldn't work properly.
However, there is some good news. Scala 2.13 introduces Using which essentially performs a try-with-resources. We can trick this into doing a more general try...finally by using a dummy resource:
Using(lock.lock())(_ => doStuff())(_ => lock.unlock())
And if you don't have anything that is idiomatically performed before the try, then you can provide a Unit in the first parameter list:
Using(())(_ => doStuff())(_ => lock.unlock())
But in any case, Try is not going to do the job.

Catching unhandled errors in Scala futures

If a Scala future fails, and there is no continuation that "observes" that failure (or the only continuations use map/flatMap and don't run in case of failure), then errors go undetected. I would like such errors to be at least logged, so I can find bugs.
I use the term "observed error" because in .Net Tasks there is the chance to catch "unobserved task exceptions", when the Task object is collected by the GC. Similarly, with synchronous methods, uncaught exceptions that terminate the thread can be logged.
In Scala futures, to 'observe' a failure would mean that some continuation or other code reads the Exception stored in the future value before that future is disposed. I'm aware that finalization is not deterministic or reliable, and presumably that's why it's not used to catch unhandled errors, although .Net does succeed in doing this.
Is there a way to achieve this in Scala? If not, how should I organize my code to prevent unhandled error bugs?
Today I have andThen checkResult appended to various futures. But it's hard to know when to use this and when not to: if a library method returns a Future, it shouldn't checkResult and log errors itself, because the library user may handle the failure, so the responsibility falls onto the user. As I edit code I sometimes need to add checks and sometimes to remove them, and such manual management is surely wrong.
I have concluded there is no way to generically notice unhandled errors in Scala futures.
You can just use Future.recover in the function that returns the Future.
So for instance, you could just "log" the error and rethrow the original exception, in the simplest case:
def libraryFunction(): Future[Int] = {
val f = ...
f.recover {
case NonFatal(t) =>
println("Error : " + t)
throw t
}
}
Note the use of NonFatal to match all the exception types it is sensible to catch.
That recover block could equally return an alternative result if you wish.

Scala exception as a function argument design pattern

I am writing a web app where exceptions are used to handle error cases. Often, I find myself writing helpers like this:
def someHelper(...) : Boolean {...}
and then using it like this:
if (!someHelper(...)){
throw new SomeException()
}
These exceptions represent things like invalid parameters, and when handled they send a useful error message to the user, eg
try {
...
} catch {
case e: SomeException => "Bad user!"
}
Is this a reasonable approach? And how could I pass the exception into the helper function and have it thrown there? I have had trouble constructing a type for such a function.
I use Either most of the time, not exceptions. I generally use exceptions, as you have done or some similar way, when the control flow has to go way, way back to some distant point, and otherwise there's nothing sensible to do. However, when the exceptions can be handled fairly locally, I will instead
def myMethod(...): Either[String,ValidatedInputForm] = {
...
if (!someHelper(...)) Left("Agree button not checked")
else Right(whateverForm)
}
and then when I call this method, I can
myMethod(blah).fold({ err =>
doSomething(err)
saneReturnValue
}, { form =>
foo(form)
form.usefulField
})
or match on Left(err) vs Right(form), or various other things.
If I don't want to handle the error right there, but instead want to process the return value, I
myMethod(blah).right.map{ form =>
foo(form)
bar(form)
}
and I'll get an Either with the error message unchanged as a Left, if it was an error message, or with the result of { foo(form); bar(form) } as a Right if it was okay. You can also chain your error processing using flatMap, e.g. if you wanted to perform an additional check on so-far-correct values and reject some of them, you could
myMethod(blah).right.flatMap{ form =>
if (!checkSomething(form)) Left("Something didn't check out.")
else Right(form)
}
It's this sort of processing that makes using Either more convenient (and usually better-performing, if exceptions are common) than exceptions, which is why I use them.
(In fact, in very many cases I don't care why something went wrong, only that it went wrong, in which case I just use an Option.)
There's nothing special about passing an exception instance to some method:
def someMethod(e: SomeException) {
throw e
}
someMethod(new SomeException)
But I have to say that I get a very distinct feeling that your whole idea just smells. If you want to validate a user input just write validators, e.g. UserValidator which will have some method like isValid to test a user input and return a boolean, you can implement some messaging there too. Exceptions are really intended for different purposes.
The two most common ways to approach what you're trying to do is to either just have the helper create and throw an exception itself, or exactly what you're doing: have the calling code check the results, and throw a meaningful exception, if needed.
I've never seen a library where you pass in the exception you expect the helper to throw. As I said on another answer, there's a surprisingly substantial cost to simply instantiating an exception, and if you followed this pattern throughout your code you could see an overall performance problem. This could be mitigated through the use of by-name parameters, but if you just forget to put => in a few key functions, you've got a performance problem that's difficult to track down.
At the end of the day, if you want the helper to throw an exception, it makes sense that the helper itself already knows what sort of exception it wants to throw. If I had to choose between A and B:
def helperA(...) { if (stuff) throw new InvalidStuff() }
def helperB(..., onError: => Exception) { if (stuff) throw onError }
I would choose A every time.
Now, if I had to choose between A and what you have now, that's a toss up. It really depends on context, what you're trying to accomplish with the helpers, how else they may be used, etc.
On a final note, naming is very important in these sorts of situations. If your go the return-code-helper route, your helpers should have question names, such as isValid. If you have exception-throwing-helpers, they should have action names, such as validate. Maybe even give it emphasis, like validate_!.
For an alternative approach you could check out scalaz Validators, which give a lot of flexibility for this kind of case (e.g. should I crash on error, accumulate the errors and report at the end or ignore them completely?). A few
examples might help you decide if this is the right approach for you.
If you find it hard to find a way in to the library, this answer gives some pointers to some introductory material; or check out .