If you're coming from a C-like language (C, C++, Java, etc.), you can think of unit as being like void
. It is the type you return when you don't want to return anything.
Type theorists will point out that unit is not like void, because unit has exactly 1 value whereas void has 0 values.
In practice, the amount of information you can store in both types is the same (0 bits), although languages that use unit tend to be nicer to work with because you can treat it as you would any other value.
You can store it in a variable, struct, collection, or anywhere else you could store a value. You can pass as an argument or return it as a result. You can create a reference to it. Etc.
So, when is that useful? Mainly when you don't care what type of value you're dealing with. It means you can write polymorphic/generic code without needing to worry about whether the value you are dealing with actually contains any information, that is, no need of a special case for whether you're storing actual data or ()
.
One example of where this is used is in HashSet
. A HashSet<T>
is actually implemented as a thin wrapper around HashMap<T, ()>
. (A map from the generic type T
to ()
)
void
in C-like languages. As far as I know, everything is an expression in rust, so()
is the value returned by something which is only executed for its effects. – Baier()
by sayingstruct MyNewZeroSizeType;
It can be useful ("marker types"!) – Brigandinenull
in java because if you say your returning anint
you can't return()
in place of it. – Absorbent