Pebellslearn by building
0%
RoadmapsMatrixCoursesSandboxSign in
Variables, Constants and Types  ›  Lesson

Unit, Nothing and the Type Hierarchy

Type Hierarchy 14 minEvery Scala type sits in one tree with Any at the top and Nothing at the bottom; Unit is the type of code run only for its effect, and Nothing is the type of code that never finishes normally.

Unit, Nothing and the Type Hierarchy

The logbook has one function that saves a run and returns nothing interesting, and another that gives up with an error when a distance is not positive. What types do those have? Scala answers with two special types, and both make sense once you see where every type lives.

The rule

Any sits on top, Nothing at the bottom; Unit means "done, nothing to report".

Every Scala type belongs to one family tree:

                    Any
                     |
                 Matchable
          ┌──────────┴──────────┐
       AnyVal                 AnyRef
  Int, Double, Boolean,    String, List,
  Char, Long, Unit, ...    your own classes
          └──────────┬──────────┘
                  Nothing
  • Any is the top. A value of any type can be stored as Any: val note: Any = 42 compiles. You lose the specific type, though, so you can do little with it afterwards.
  • AnyVal holds the value types: the numbers, Char, Boolean and Unit.
  • AnyRef holds the reference types: String, collections and every class you write. It is the same as Java's Object.
  • Matchable sits between Any and those two branches in Scala 3. It matters for advanced pattern matching; you can ignore it for now.
  • Nothing is at the bottom, below every other type.

Unit has exactly one value, written (). It is the result of code run only for its effect:

def logRun(km: Double): Unit =
  println(s"Logged $km km")

val saved = logRun(8.5)   // prints the line; saved is ()

Nothing has no values at all. An expression of type Nothing never finishes normally. A throw has type Nothing, and so does ???, which means "not written yet" and throws when reached. Because Nothing sits below every type, it fits anywhere:

def pace(seconds: Int, km: Double): Double =
  if km > 0 then seconds / km
  else throw IllegalArgumentException("distance must be positive")

The then branch is a Double and the else branch is Nothing, so the whole if is a Double.

There is also Null, the type of null, which sits below the reference types. Scala code avoids null; you will meet safer tools for missing values later.

The shortcut

Top accepts everything; bottom fits everywhere. Any value can go up into Any. A Nothing expression can go into any slot. And Unit is a real value, (), not an absence.

Typing three lines of the logbookStep 1 of 3
  1. Store a note as Any

    val note: Any = 42 compiles, because every type sits under Any.

The trap: thinking Unit and Nothing are the same. Unit means the code finished and has nothing to say; Nothing means it never finished normally.

Drills

Answer fast — trust the rule.

quick drill

Which type is at the top of Scala's type hierarchy?

quick drill

What value does println("saved") return?

quick drill

Why is if km > 0 then seconds / km else throw IllegalArgumentException("bad") a Double?

quick drill

Which of these is an AnyVal type?

quick drill

val todo: String = ??? — what happens?

Remember

  • Any is the top and Nothing the bottom; AnyVal holds values like Int, AnyRef holds references like String.
  • Top accepts everything, bottom fits everywhere; Unit is the real value ().
  • Trap: mixing up Unit (finished, nothing to report) and Nothing (never finished).

Practice — level up

0/1 solved

Write your answer, then compare it with a rubric and a model answer.

ExplainFinished or never finished?

Explain the difference between Unit and Nothing using two logbook functions: logRun, which prints a line, and pace, which throws when the distance is not positive. Include where each type sits in the hierarchy and why pace can still declare Double as its result.