什么是从不返回类型?

问题描述:

返回类型为 Neverfunc 有什么作用?

What does a func with return type Never do?

例如:

func addNums() -> Never {

    //my code

}

如果我像这样将返回类型保持为 Void 会有什么不同?

What will be the difference if I kept the return type as Void like this?

func addNums() -> Void {

    //my code

}

假设我希望处理 fatalError(如 dpassage 所述);下面的代码就足够了:


Suppose I wish to handle a fatalError (as said by dpassage); the below code will be sufficient:

print("its an error")
return

Apple 文档说:

不正常返回的函数的返回类型,即没有值的类型.

The return type of functions that do not return normally, that is, a type with no values.

来源:Developer

这不是 何时以及如何在 Swift 中使用 @noreturn 属性的重复问题?,正如我所希望的需要详细信息的更详细的答案,例如:

This was not a duplicate question of When and how to use @noreturn attribute in Swift?, as I wish for a more detailed answer which needs details like:

  1. NeverVoid 作为返回类型的区别的实例

  1. Practical examples on the difference between both Never and Void as return types

我们应该采用这些返回类型的条件.

Condition by which we should adopt these return types.

返回类型也有可能为零;我也需要比较那个功能

Also there is a chance the return type can be nil; I need a comparison of that feature too

答案应侧重于差异.

Never 返回类型是在 Swift 3 中引入以替代 @noreturn 键.

Never return type was introduced in Swift 3 to substitute @noreturn key.

请参阅此提案中的理由:
SE-0102 移除@noreturn 属性并引入空的 Never type

See justification in this proposal:
SE-0102 Remove @noreturn attribute and introduce an empty Never type

如官方文档所述:

不正常返回的函数的返回类型;一种类型没有价值.

The return type of functions that do not return normally; a type with no values.

在声明闭包时使用 Never 作为返回类型,无条件抛出错误、陷阱或否则不会终止.

Use Never as the return type when declaring a closure, function, or method that unconditionally throws an error, traps, or otherwise does not terminate.

来源:https://developer.apple.com/documentation/迅速/从不

基本说明:

// The following function is our custom function we would use
// to manually and purposefully trigger crash. In the logs,
// we can specify what exactly went wrong: e.g. couldn't cast something, 
// couldn't call something or some value doesn't exist:
func crashApp() -> Never {
    fatalError("Something very, very bad happened! Crash the app!")
}

使用细节和优于 @noreturn 的优势,如 埃丽卡·萨顿:

Usage specifics and advantages over @noreturn, as referenced by Erica Sadun:

  • 永远不允许函数或方法抛出:例如() 抛出 -> 从不.抛出允许错误修复的辅助路径,即使在预期不会返回的函数中也是如此.
  • 作为第一类类型,从不以@noreturn 属性无法使用的方式使用泛型.
  • 永远不要主动阻止函数同时声明返回类型和不返回.这是旧系统下的潜在问题.

第一个注意事项(关于二次错误修复)可能特别重要.Never 函数可以有复杂的逻辑并抛出 - 不一定会崩溃.

First note (regarding secondary error remediation) is probably particularly important. Never function can have complex logic and throw – not necessarily crash.

让我们看看一些有趣的用例以及 NeverVoid

Let's see some interesting use cases and comparison between Never and Void

示例 1

func noReturn() -> Never {
    fatalError() // fatalError also returns Never, so no need to `return`
}

func pickPositiveNumber(below limit: Int) -> Int {
    guard limit >= 1 else {
        noReturn()
        // No need to exit guarded scope after noReturn
    }
    return rand(limit)
}

示例 2

func foo() {
    abort()
    print("Should not reach here") // Warning for this line
}

示例 3

func bar() -> Int {
    if true {
        abort() // No warning and no compiler error, because abort() terminates it.
    } else {
        return 1
    }
}

abort() 定义为:

public func abort() -> Never

无效

如果它返回 Void,这些例子是不可能的:

Void

These examples would not have been possible with it returning Void:

public func abortVoid() -> Void {
    fatalError()
}

func bar() -> Int {
    if true {
        abortVoid() // ERROR: Missing return in a function expected to return 'Int'
    } else {
        return 1
    }
}

并用 abort() 返回 Never 打包:

And to pack it up with abort() returning Never:

func bar() -> Int {
    if true {
        abort() // No ERROR, but compiler sees it returns Never and warns:
        return 2 // Will never be executed
    } else {
        return 1
    }
}

我们使用Void 来告诉编译器没有返回值.应用程序一直在运行.

We use Void to tell compiler there is no return value. Application keeps running.

我们使用Never 来告诉编译器没有返回调用者站点.应用程序运行循环终止.

We use Never to tell compiler there is no return to caller site. Application runloop is terminated.