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
└──────────┬──────────┘
NothingAnyis the top. A value of any type can be stored asAny:val note: Any = 42compiles. You lose the specific type, though, so you can do little with it afterwards.AnyValholds the value types: the numbers,Char,BooleanandUnit.AnyRefholds the reference types:String, collections and every class you write. It is the same as Java'sObject.Matchablesits betweenAnyand those two branches in Scala 3. It matters for advanced pattern matching; you can ignore it for now.Nothingis 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.
Store a note as Any
val note: Any = 42compiles, 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.
Which type is at the top of Scala's type hierarchy?
What value does println("saved") return?
Why is if km > 0 then seconds / km else throw IllegalArgumentException("bad") a Double?
Which of these is an AnyVal type?
val todo: String = ??? — what happens?
Remember
Anyis the top andNothingthe bottom;AnyValholds values like Int,AnyRefholds references like String.- Top accepts everything, bottom fits everywhere;
Unitis the real value(). - Trap: mixing up Unit (finished, nothing to report) and Nothing (never finished).
