scala – Why we need Nothing, Null, Nil and None

Question:

Judging by the names, all types mean the same thing. In what cases in scala should you use: Nothing , Null , Nil and None , how do they differ?

Answer:

Well written here . I will add something, I will summarize something.

The Nothing type is the lowest type. This means that variables with this type can be assigned to absolutely any other type.

Example 1:

def isTen(number: Int): Boolean =
  if (10 == number) true
  else throw new Exception("Number is not ten")

true is of type Boolean , throwing an exception is of type Nothing , and since Nothing inherits Boolean in the type hierarchy, the result is Boolean .

Example 2:

def genericIsTen[T](value: T): T =
  if (10 == value) value
  else throw new Exception("Generic is not ten")

Since Nothing is the lowest type, it means that in the type hierarchy the heir of any type – instead of Boolean can be a generic.

Example 3:

trait Box[+T]

case class Full[T](value: T) extends Box[T]
object Empty extends Box[Nothing]

def boxedIsTen(value: Int): Box[Int] =
  if (10 == value) Full(value)
  else Empty

Similarly to the examples above, an object with the Box[Nothing] type is easily assigned to the Box[Int] type (due to the covariance , i.e. that trait's plus sign).

The conclusion, as you can see, the type Nothing is used when you need the type to be accepted by another type. "Frayed" by another type.


The Null type is almost the lowest type. In the type hierarchy, it is the heir of all objects, but not the heir of all primitives. This means that it will work for objects in the same way as Nothing.

isTen(null) // НЕ будет работать так как функция хочет примитив
genericIsTen((null) // будет работать
boxedIsTen(null) // НЕ будет работать так как функция хочет Int

Nil is not a type, it's a Nil object. The type of this object is Nil.type . The Nil object is one of two descendants of the List class and is used where an empty list of type List is needed. Well, since it is the heir of List , all its methods are available to it.

sealed abstract class List[+A] { /* ... */ }

case object Nil extends List[Nothing] { /* ... */ }
final case class ::[B]( /* ... */ ) extends List[B] { /* ... */}

def listIsTen(number: Int): List[Int] =
  if (10 == number) List(number)
  else Nil

None is not a type either, but a None object. The type of this object is None.type . The None object is one of two descendants of the Option class and is used as an empty Option .

sealed abstract class Option[+A]

case object None extends Option[Nothing] { /* ... */ }
final case class Some[+A](x: A) extends Option[A] { /* ... */ }

def optionIsTen(number: Int): Option[Int] =
  if (10 == number) Some(number)
  else None
Scroll to Top