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

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

Related

Rx.Net ignore certain exceptions but handle rest of the exceptions

It is easy to handle a particular set of exceptions using the Catch operator. How could we ignore certain exceptions but handle the rest in the Catch block?
Say for example I would like to let ArgumentNullException, ArgumentOutOfRangeException and TimeoutException exceptions bubble and report an error but for anything else I would like to retry.
The catch version below would catch all the exceptions, and there is no way to selectively ignore some types, as the signature requires it to return a IObservable<T>
source.Catch<T, Exception>(e=> Observable.Return(default(T)))
If I have to retry on certain Exception then I could write something like (I think)
source.Catch<T, WebException>(e=> source.Retry())
A very meaningful operator in these situations is RetryWhen.
RetryWhen(selector) gives you an observable of Exception, and expects an observable which, triggers a retry every time it produces a value.
RetryWhen(e => e) is equivalent to Retry() (all exceptions trigger a retry).
RetryWhen(e => e.Take(3)) is equivalent to Retry(3) (first three exceptions trigger a retry).
Now you can simply transform the inner sequence into one that emits on your desired types of exceptions. For example, to only retry on TimeoutException:
source.RetryWhen(e => e.Where(exn => exn is TimeoutException))

In which cases does try-catch catch exceptions?

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!")
}

I'm not a programmer: does 'throw' mean a specific code element or is a general term like 'show'?

For example:
An unguarded throw of type {0} was detected. Refactor this code to either throw an exception of type InvalidPluginExecutionException or guard against thrown exceptions of other types.
What could the first 'throw' mean? Is it a synonym for 'show' or 'return'?
Most languages allow the "throwing" of exceptions. If a function throws an exception, it means that under certain logic paths it chooses not to gracefully handle an problem and passes it on to the user to handle.
In your case, it would seem:
you are using a typed language
the compiler knows which functions throw exceptions
the compiler does not allow / warns against unhandled (unguarded) exceptions
You are likely using a function that can throw an exception under certain cases and your code does not "catch" (handle) that exception, leading to certain cases in which your code is implicitly throwing an exception despite you not explicitly writing any exception throwing code. The compiler is telling you to handle the implicit case by handling the exception (in most languages this is accomplished with some sort of "try..catch") and:
explicitly throw the exception
gracefully handle the exception

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.

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.