Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why Scala does not have concept of checked and unchecked exception?

I have following two questions :

  1. Why Scala does not have concept of Checked and Un-checked exception?
  2. What are the advantages or disadvantages of not supporting checked exceptions?
like image 802
Yogesh Patil Avatar asked Dec 09 '16 09:12

Yogesh Patil


People also ask

Why Scala does not have checked exception?

The case of Checked Exceptions Scala does not have checked exceptions. The compiler does not enforce exceptions to be handled. For example, the below code which is a direct translation of the above java code block compiles just fine. It will throw an error if there is no such file is present only at the run time.

What is the problem with unchecked exceptions?

Unchecked exception example Because the compiler can't anticipate logical errors that arise only at runtime, it can't check for these types of problems at compile time. That's why they are called "unchecked" exceptions. Unchecked exceptions result from faulty logic that can occur anywhere in a software program.

What are exceptions in Scala?

An exception is an event that changes the normal flow of a program. Exception handling is the mechanism to respond to the occurrence of an exception. Exceptions can be checked or unchecked. Scala only allows unchecked exceptions, though.

Can we create checked and unchecked exception?

Custom Checked and Custom Unchecked All exceptions must be a child of Throwable. If you want to write a checked exception that is automatically enforced by the Handle or Declare Rule, you need to extend the Exception class. If you want to write a runtime exception, you need to extend the RuntimeException class.


3 Answers

I don't know the exact reason why Scala chose not to have checked exception, but one can say that's the common approach. How many other languages do you know that have checked exceptions besides java?

I will point out something I saw in a lot of java programs over the years, and I'm sure if you did serious java programming you have seen it too:

try {
  // do stuff
} catch (Exception e) {
  throw new RuntimeException(e);
}

try {
  // do stuff
} catch (Exception e) {
  // do nothing
}

Sure you can say that's lazy programming, and the latter truly is. But it shows you a problem. You sometimes can't and don't want to handle the exception in place, you want the program to break, or the exception to bubble up to a higher-level component that will handle the errors.

And you may be thinking right now You just need to add throws in the method signature but more often than not you can't. And I can give you a clear example of this problem using java 8 lambdas.

list.stream().map(item -> {
  // throws a checked exception. compilation error
  return normalizeItem(item);
});

In the code above, you will need to handle the exception, using one of the two techniques shown above. You can of course create a new functional interface that throws an exception, but you will need to recreate all the standard ones just to annotate them with throws. If you ask me, this is a real mess.

I think that's one of the reasons. Scala is functional from the beginning and checked exceptions don't go well with this, as you can see.

You can read a much more thorough discussion here

like image 105
Tiago Engel Avatar answered Oct 12 '22 13:10

Tiago Engel


TL;DR jump to last paragraph :)

While I completely agree with Tiago's answer, there are a few things that can be added. As you know, Scala is a functional and object-oriented language. The functional aspect of it dictates that side-effects should be eliminated, or at least minimized as much as possible.

Throwing an exception is a side-effect since it is not referentially transparent (ie, it depends on the context of where the exception is thrown, for example if the exception is thrown from inside a try block, it will be caught whereas if it is thrown outside of that try block, it will alter the flow of the program).

Here is an example taken from the book Functional Programming in Scala (P. Chiusano, R. Bjarnason)

 def failingFn(i: Int): Int = {
       val y: Int = throw new Exception("fail!")
       try {
         val x = 42 + 5
         x + y
       }
       catch { case e: Exception => 43 }
 }

In the above code, y is not referentially transparent since if you replace it by its value within the try block, the result of the function will be different.

Ok, enough with all the theory, the key takeaway from the above is that throwing an exception is a side-effect and this violates the functional programming paradigm.
To address this, the designers of Scala decided to instead return "a value" that indicates that an exception occurred, instead of throwing one. For that reason, classes like Try (and its direct subtypes Success and Failure) were introduced. Instead of throwing an exception, you simply modify the return type of your function, wrapping it in a Try. This forces the client to check for success or failure without all the side-effects that throwing exceptions bring. The introduction of the Try type basically replaces checked exceptions since the client is implicitly made aware of the possibility of an exception at compile-time through the use of a Try return type.

like image 42
Joud C Avatar answered Oct 12 '22 11:10

Joud C


Starting Scala 3.1.0-RC1 exception checking can be enabled by

import language.experimental.saferExceptions

For example

scala> import language.experimental.saferExceptions

scala> def foo(): Int = throw new Exception()
-- Error:
1 |def foo(): Int = throw new Exception()
  |                 ^^^^^^^^^^^^^^^^^^^^^
  |        The capability to throw exception Exception is missing.
  |        The capability can be provided by one of the following:
  |         - A using clause `(using CanThrow[Exception])`
  |         - A `throws` clause in a result type such as `X throws Exception`
  |         - an enclosing `try` that catches Exception
  |
  |        The following import might fix the problem:
  |
  |          import unsafeExceptions.canThrowAny
  |

scala> def foo(): Int throws Exception = throw new Exception()
def foo(): Int $throws Exception

The mechanism that enables the compiler to track these exceptions is called capabilities and is implemented by context functions. Note that error capabilities are different from error effect tracking via error monads (such as Either, Option, Try, etc.)

capabilities can be expressed as parameters whereas traditionally effects are expressed as some addition to result values.

This means there is no need to modify the return types in order to track the error, for example consider the difference between

scala> def foo(): Try[Int] = Success(42)       // we have to wrap 42
def foo(): util.Try[Int]

scala> def foo(): Int throws Exception = 42    // just pure 42
def foo(): Int $throws Exception

As to possible reason why Scala did not implement Java's checked exception mechanism same document explains

The main problem with Java's checked exception model is its inflexibility, which is due to lack of polymorphism.

like image 40
Mario Galic Avatar answered Oct 12 '22 13:10

Mario Galic