What is the Never return type?

前端 未结 4 1462
我在风中等你
我在风中等你 2021-01-01 10:36

What does a func with return type Never do?

For example:

func addNums() -> Nev         


        
4条回答
  •  心在旅途
    2021-01-01 10:53

    To better understand Never and Void, and how Never is useful in more contexts than the old @noreturn was, let's first look at what the two types actually are defined as:


    Never is defined here as:

    public enum Never {}
    

    Since there is no way to instantiate a value of an empty enum, the type system guarantees that no instance of Never can exist. This means functions that specify their return type as Never are prevented by the type system from actually returning under any circumstances.

    The compiler takes this into account when doing control-flow analysis. For example, these two functions both compile without error, whereas they would fail if a function that returns Void was substituted for fatalError:

    func foo(fail: Bool) -> String {
        if fail {
            fatalError()
        } else {
            return "foo"
        }
        // notice there is no return statement here
    }
    
    func bar(fail: Bool) -> Void {
        let s: String
        if fail {
            fatalError()
            // the compiler doesn't complain s is not initialized here
        } else {
            s = "bar"
        }
        print(s)
    }
    

    Void is defined here as:

    public typealias Void = ()
    

    There are no two different instances of an empty tuple. Thus, the return value of functions returning Void holds no information.

    You can actually write return () or return Void(). You can also use the "value" returned, like this:

    func empty() -> Void {}
    let v = empty()
    print(type(of: v)) // prints "()"
    

    although the compiler will warn "Constant 'v' inferred to have type 'Void', which may be unexpected".


    Defining both Never and Void in terms of the type system rather than as special language features enables us to do some pretty clever things with generics. Let's look at an example of a Result type, generic over both the success and failure type.

    enum Result {
        case success(R)
        case failure(E)
    }
    

    A possible specialization of this would be Result. This would mean you have a result that, on success, does not hold any information beyond the fact it succeeded.

    Another possibility could be Result. This result is guaranteed by the compiler to never be the failure case.

    Optionals interact with Never and Void in a similar way. Never? can only ever be nil, and Void? only holds the information wether it is nil or not, nothing more (it's basically a more complicated Bool). Both of these are not very useful on their own, but might appear when Never or Void are used as generic parameters somewhere.


    In practice, you will rarely write functions returning Never. I have personally used it to wrap fatalError to create a function I use to mark functions that are not implemented yet:

    func unimplemented(f: String = #function) -> Never {
        fatalError("\(f) is not implemented yet")
    }
    

    Another example of a function returning Never is dispatchMain(), which can be used in command-line utilities to start the DispatchQueue.main. Since this queue then waits for new blocks, dispatchMain() never returns.

提交回复
热议问题