Radu Dan
Swift gems nil, Void and Never

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:

Warning on tuples

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:

Closure errors

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: