3

I'd like to clarify some details about Unit and Nothing.

For example:

def unit(companyId: Int): Unit = {}

def Nothing(companyId: Int): scala.Nothing = {}

According to the docs, Unit in Scala is very similar to void in Java. But

test("test Unit and Nothing") {
  println(unit(1))
}
  • Unit return - ()

  • Nothing does not return anything.

Why does Scala has overflow type Unit which return Nothing? Why Scala cannot useNothing instead of Unit?

Chris Martin
  • 30,334
  • 10
  • 78
  • 137
  • 1
    Possible duplicate of [Usages of Null / Nothing / Unit in Scala](http://stackoverflow.com/questions/16173477/usages-of-null-nothing-unit-in-scala) – Tzach Zohar Mar 07 '16 at 21:47
  • 3
    What do you mean by "overflow"? – Chris Martin Mar 07 '16 at 22:03
  • Welcome to StackOverflow! To show appreciations for your peers taking time to answer your questions please accept their answers: http://stackoverflow.com/help/someone-answers – manub Mar 16 '16 at 16:39

1 Answers1

13

Unit has cardinality 1. Nothing has cardinality 0.

Your second example

def Nothing(companyId: Int): scala.Nothing = {}

doesn't compile. It's impossible to return a Nothing, because Nothing has no inhabitants. Therefore a function that returns Nothing cannot return normally; it can only throw an exception.

def Nothing(companyId: Int): scala.Nothing = { throw new Exception(); }

Java's Void is comparable to Unit in that Void also has cardinality 1; its sole inhabitant is null. There is no type with cardinality 0 in Java (nor is it possible to define such a type), so Java does not have a type that is comparable to Nothing. It is, of course, possible to write a Java method that always throws an exception, but it is not possible for the return type to express that.


Consider what happens when you use each of these in collections. For example, a List[Unit] can contain any number of Unit values:

List()           : List[Unit]
List((), (), ()) : List[Unit]

whereas a List[Nothing] is necessarily empty, because there is nothing you can put into it.

List()           : List[Nothing]

The other important thing to note about Nothing is that it's a subtype of every other type. This makes sense, because it has no inhabitants; therefore every proposition (propositions are closely related to types) about Nothing instances holds vacuously. For an example of why this is useful, again consider lists:

List.empty[Nothing] : List[String]

Here we ascribe a List[Nothing] to the type List[String], which we can do because List's type parameter is covariant and Nothing is a subtype of String. Note that we couldn't do that with a List[Unit], because Unit is not a subtype of String.

Chris Martin
  • 30,334
  • 10
  • 78
  • 137
  • Thank you for your detailed explanation. I'm familiar with List[Nothing], Nil, Liskov substitution and so on. But my question is different. Why if function does not return data, need to use Unit and in fact return () instead of Nothing. –  Mar 09 '16 at 12:45
  • @scala Maybe this blogpost http://james-iry.blogspot.ch/2009/08/getting-to-bottom-of-nothing-at-all.html?m=1 might help giving you some additional intuition – godfatherofpolka Mar 16 '16 at 22:00