Swift's gems: nil, Void and Never
Motivation
This article gives you a snippet of what is nil
, Void
and Never
in Swift terminology.
We want to cover some basic usage of these three gems so you will have a clear understanding of their differences.
nil
The absence of a value.
When we are saying nil, we are bringing to the table 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 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 an empty tuple (). It is implemented with a typealias: typealias Void = ()
.
The usage is for functions that don't return values. This is the default return type for functions or closures if not specified otherwise.
Example #1:
func doSomeStuff() {
// magic stuff
}
It is the same thing as:
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 which type is Void and returns Void (no values).
Could we have written: completion: (Void) -> ())
? Yes, but if you are using Swift 4 or above, we have a compile warning:
The compiler wants us to remove the Void. As the language evolved, the tuples are now handled with more restrictions.
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
}
}
First closure doSomeStuff
returns a parameter which value is Void. The second closure doesn't return anything.
You can try writing result in
for second function, but the compiler will now give you an error:
Never
Something that will never return.
Never
appeared in Swift 3 and it removed the @noreturn
attribute and introduced an empty type.
It is implemented as an empty enum: enum Never {}
.
You can read the proposal here.
It helps the compiler to understand which functions will never return. This brings the discussion of how Never is different from Void.
Void vs Never
- Implementation: Void is a tuple, Never 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 can't 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 why.")
}
// 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("Stuff happens when there are more than five numbers!")
}
// do some stuff
}
// preconditionFailure declaration
func preconditionFailure(_ message: @autoclosure () -> String = String(),
file: StaticString = #file,
line: UInt = #line) -> Never
Conclusion
We saw some common usages of Swift's: nil, Void and Never.
The most uncommon one is Never, it is rarely used in apps and at a first glance you can say is the same as Void, but we saw together that this is not the case.
Optionals are at the heart of Swift APIs, they are used everywhere and it is important to understand why and what they are solving. I recommend a great article if you are a beginner and want to understand them better: https://hackernoon.com/swift-optionals-explained-simply-e109a4297298.
Void I believe you heard of it from different languages, such as C/C++ and it means that the function doesn't return a value (a return type without values).
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
References
[1] The Swift Programming Language (Swift 5), chapter Language Guide, The Basics - https://docs.swift.org/swift-book/LanguageGuide/TheBasics.html
[2] Article from nshipster.com - Never - written by Matt (@Matt) - https://nshipster.com/never/
There are some great articles out there that go more in depth:
- Tweet from David Smith from objc.io
- NSHipster article about Never
- The Macro Behind nil by Ben Ford
- This topic on Stack Overflow
- Three Kinds of Nothing
- Swift evolution proposal of Never
- NSHipster article about Void