Mandroid
Mandroid

Reputation: 7494

Scala: Nothing and throw expression

scala.Nothing is a type with no value of this type.

In scala a 'throw' expression has type Nothing, and also an expression evaluates to a value.

Don't these 2 contradict?

Upvotes: 0

Views: 494

Answers (2)

slouc
slouc

Reputation: 9698

Short answer:

No. It's just clumsy wording. On the type level, expressions always evaluate to some type. One of those types is Nothing, so-called "bottom type" that sits on the bottom as a subclass of all other types. It's a type without actual values, which means that expressions that resolve into type Nothing (such as throw expressions) don't evaluate to a value. This is an exception to the "expression always evaluates to a value" rule. And if Scala were a pure FP language, that rule would hold without exceptions (pun totally intended).

Long answer:

Throwing is not only hard to reason about in functional programming because it produces a side-effect, but it is also hard to reason about in a statically typed language because you can't reason about assigning a type if you have no value. And that's exactly what happens here - instead of resolving into a value, you simply "explode". Thrown exceptions transcend the boundaries of statically typed code by ripping its fabric and creating a portal which allows them to continue their journey in a different dimension.

Poetic notions aside, even though throwing is tricky to reason about in the context of a strongly, statically typed functional programming language such as Scala, it needs to exist (due to Scala being based on the JVM and having an OOP side as well) so it has to somehow play well with the compiler and the type system.

So what we do is, we simply assign such expressions the type Nothing. Note that I'm using the word "expression", because normally I would say "assign such values", but here there is no value.

Take a look at the following example:

def myFunction(i: Int): String = i match {
  case 42 => "Fourty two"
  case _  => throw new Exception("Not fourty two")
}

Above function returns a String. However, the second pattern matching case throws an exception. Does that resolve into a value of type String? No. It doesn't even resolve into a value in the first place! But in order to make such things work in the context of a typed system, we have to assign a type to the whole throw ... expression. And in order to make such expressions work everywhere, no matter which type is expected (in the above example it's String), we simply make it resolve into a bottom type = Nothing.

This means that:

  1. Throw statements will compile wherever you put them, which is a requirement of having such statements in the first place (otherwise you might as well just ditch them from the language)

  2. Reasoning about throw statements being treated as expressions of type Nothing makes sense, because Nothing is a type that cannot take any values, and throw statement also cannot ever resolve into a value. That's my metaphore from earlier about how it tears up the fabric of the program - you enter a code path that promised to resolve into a String, but instead of coming back with a value of type String, you instead somehow escape without ever resolving into a value at all. Remember, pure FP language should never allow exceptions to exist in the first place.

Upvotes: 5

sinanspd
sinanspd

Reputation: 2734

There are a few uses of Nothing in Scala

  1. Express variance in the type parameters (since it is never instantiated, this does make the underlying implementation easier from the type system perspective)

  2. A piece code might "return" the type Nothing if it never returns. This is the important distinction between Unit & Nothing, in Unit you still return but you return a void value, whereas in the case of Nothing you don't actually return. This is in fact the case for exception handling and there are good reasons behind this, passing around the control of the program.. Exception handling is usually implemented using/in a similar fashion to automatic callback insertion(ACI)/continuation passing style (CPS). That is when this code is compiled, there are callbacks inserted into the code for the exception throwing function to pass the control, with some custom stack, to where ever the exception needs to be handled. Borrowing from other languages, if you are interested in how this works, you can look at Scheme's call/cc, or Racket's let/cc which pretty much simulates exception handling.

That is do some computation -> when you hit an exception, no matter how much more things there are to be computed, bail out, discard everything, go back to the original stack.

Upvotes: 3

Related Questions