Rust has the unit type, ()
, a type with a single zero-size value. The value of this unit type is also specified using ()
.
What is the purpose of the unit type and its value? Is it a mechanism to avoid using null (or nil) like other languages have?
()
is a value of the type ()
and its purpose is to be useless.
Everything in Rust is an expression, and expressions that return "nothing" actually return ()
. The compiler will give an error if you have a function without a return type but return something other than ()
anyway. For example
fn f() {
1i // error: mismatched types: expected `()` but found `int`
}
There are practical uses for ()
too. Sometimes we don't care about a generic type, and ()
makes this explicit.
For example, a Result<(), String>
can be used as return type for a function that either completes successfully or fails for a variety of reasons.
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 ()
)