Swift’s gems: nil, Void and Never
Motivation
This article provides a concise overview of nil
, Void
, and Never
in Swift terminology. We will explore the basic usage of these three gems to ensure you have a clear understanding of their differences.
nil
The absence of a value.
When we mention nil
, we are addressing Swift's optionals.
Optionals say either “there is a value, and it equals x” or “there isn’t a value at all”. [1]
Under the hood, an Optional
is defined as an enum
:
enum Optional<Wrapped>: ExpressibleByNilLiteral {
case none
case some(Wrapped)
}
Example:
let greeting: String? = nil // preferred
let greeting2: String? = .none // same thing
let greeting3: Optional<String> = .none // same thing
Void
A return type that doesn’t return a value.
Void
is implemented as an empty tuple: typealias Void = ()
. This is the default return type for functions or closures unless specified otherwise.
Example #1:
func doSomeStuff() {
// magic stuff
}
This is equivalent to:
func doSomeStuff() -> Void {
// magic stuff
}
Example #2:
func doSomeStuff() {} // preferred
func doSomeStuff2() -> Void {} // same thing
func doSomeStuff3() -> () {} // same thing
Example #3:
func doSomeStuff(completion: () -> Void) {
// magic stuff
}
In this example, we have a closure that takes an argument of type Void
and returns Void
(no values).
Could we have written completion: (Void) -> ()
? Yes, but if you are using Swift 4 or above, you will receive a compile warning:
The compiler encourages us to remove the Void
type. As the language has evolved, tuples are now subject to stricter handling.
But is completion: (Void) -> ()
the same as completion: () -> ()
? Let's see:
func doSomeStuff(completion: (Void) -> ()) {}
func doSomeStuff2(completion: () -> ()) {}
And call the methods from outside:
func outside() {
doSomeStuff { result in
// some closure stuff
}
doSomeStuff2 {
// some closure stuff
}
}
The first closure in doSomeStuff
returns a parameter with the value Void
, while the second closure does not return anything.
You can attempt to write result in
for the second function, but the compiler will give you an error:
Never
Something that will never return.
Never
signifies that a function will never return. Introduced in Swift 3, it replaced the @noreturn
attribute with an empty type. It is implemented as an empty enum:
enum Never {}
For further details, you can read the documentation here.
Never
helps the compiler understand which functions will never return a value. This brings us to the distinction between Never
and Void
.
Void vs Never
Never
informs the compiler that there is no need to return a value. It is used in methods that will unconditionally throw an error or crash the system.
Never
cannot be constructed; it is an uninhabited type.
- Implementation:
Void
is a tuple, whileNever
is an empty enum. Never
informs the compiler that there is no need to return a value.Never
is used in methods that will unconditionally throw an error or crash the system.Never
cannot be constructed, is an uninhabited type [2].
Common usages:
Example #1 — fatalError
func dumpAndCrush() -> Never {
// export output to log
// save
fatalError("App went dark! Check the logs for details.")
}
// fatalError declaration
func fatalError(
_ message: @autoclosure () -> String = String(),
file: StaticString = #file,
line: UInt = #line
) -> Never
Example #2 — preconditionFailure
func doSomeStuff(with numbers: [Int]) {
guard numbers.count > 5 else {
preconditionFailure("More than five numbers are required!")
}
// do some stuff
}
// preconditionFailure declaration
func preconditionFailure(
_ message: @autoclosure () -> String = String(),
file: StaticString = #file,
line: UInt = #line
) -> Never
Conclusion
We have explored the common usages of Swift’s nil
, Void
, and Never
. While Never
is the least common of the three and may initially appear similar to Void
, we have established that they serve different purposes.
Optionals lie at the heart of Swift APIs and are used extensively. It is crucial to understand their purpose and functionality. For beginners seeking to understand optionals better, I recommend this excellent article: Swift Optionals Explained Simply.
nil
denotes the absence of a value, Void
indicates a return type that doesn't return a value, and Never
signifies something that will never return.
- nil is the absence of a value
- Void is a return type that doesn’t return a value
- Never is something that will never return
Useful links
There are some great articles out there that go more in depth: