Swift Task extension: Success == Sendable, Failure == Error necessary?

huangapple go评论64阅读模式
英文:

Swift Task extension: Success == Sendable, Failure == Error necessary?

问题

在苹果文档中看到 `Task` 被定义为:

```swift
@frozen struct Task<Success, Failure> where Success : Sendable, Failure : Error

我看到很多在线代码中,人们会为 Task 添加像这样的扩展约束:

extension Task where Failure == Error {}

以及

extension Task where Success == Sendable {}

例如,这里 的代码通过添加约束 Failure == Error 扩展了 Task。鉴于 Task 被定义为约束 Failure: Error,我想知道为什么需要添加 Failure == Error 的具体原因。

谢谢!


<details>
<summary>英文:</summary>

Seeing in the Apple doc that the `Task` is defined as:

```swift
@frozen struct Task&lt;Success, Failure&gt; where Success : Sendable, Failure : Error

I've seen a number of code online where people add extensions to Task with constraint like:

extension Task where Failure == Error {}

and/or

extension Task where Success == Sendable {}

For example, the code here extends Task with the constraint Failure == Error. Given that Task is defined with constraint Failure: Error I wonder what's the specific need for adding Failure == Error?

Thanks!

答案1

得分: 1

一种类型满足 : Error 约束,如果它符合 Error。例如,这个类型:

enum MyError: Error {
    case somethingBadHappened
}

然而,MyError 不满足 == Error 约束,因为满足这个约束的唯一类型是 Error 本身。毕竟它说的是 "等于" Error

你可以将相同的逻辑应用到 Sendable 上。

Task.initTask.detached 的版本,它们接受一个可抛出闭包,以及你链接的代码中的 relayResult,都需要 == Error,因为它们都从可抛出闭包创建任务。

你不知道可抛出闭包将会抛出什么特定类型的 Error。你唯一知道的是它会抛出 Error。因此,这些方法只能创建一个失败类型完全是 Error 的任务。它们不能创建一个失败类型是,比如,MyError 的任务,

// 假设允许使用 Failure 为 MyError 调用 Task.init
Task<SomeSuccessType, MyError> {
    // 一些会抛出 AnotherError 的代码
}

因为可抛出闭包可以抛出 AnotherError

但假设“抛出其他类型的错误”问题以某种方式被神奇地处理,== Error 也作为编译器在调用这些方法时推断 Failure 类型的简单方法。你不需要显式地写出任务可以抛出的错误类型,就像我上面所做的那样。

我暂时想不到你何时会 正好Sendable 用作 Success 类型。这似乎并不非常有用。

Sendable 没有任何语法要求,因此它在功能上与将 Void(也称为 (),并符合 Sendable)正好用作 Success 类型相同,以表示 "这个任务只是 "完成",没有结果"。如果我要选择的话,我肯定会选择 Void 而不是 Sendable 来表达这个想法。

英文:

A type satisfies the : Error constraint if it conforms to Error. For example, this type:

enum MyError: Error {
    case somethingBadHappened
}

However, MyError does not satisfy an == Error constraint, because the only type that satisfies this constraint is Error itself. It says "equal to" Error, after all Swift Task extension: Success == Sendable, Failure == Error necessary?

You can apply the same logic to Sendable.

The versions of Task.init and Task.detached that take a throwing closure, and relayResult in your linked code, all requires == Error, because they all create tasks from a throwing closure.

You don't know what specific type of Error a throwing closure is going to throw. The best you know is it throws Error. Therefore, these methods can only create a task whose failure type is exactly Error. They cannot create a task whose failure type is, say, MyError,

// let&#39;s say that calling Task.init with Failure being MyError is allowed
Task&lt;SomeSuccessType, MyError&gt; {
    // some code that throws AnotherError
}

because the throwing closure can throw AnotherError.

But let's say the "throwing other types of errors" problem is magically handled somehow, this == Error also serves as an easy way for the compiler to infer the Failure type when you call these methods. You don't need to write the type of error the task can throw explicitly, like I did above.

I can't think of when you would use exactly Sendable as the Success type off the top of my head though. That doesn't seem very useful.

Sendable doesn't have any syntactic requirements, so it is functionally the same as using exactly Void (aka (), and also conforms to Sendable) as the Success type, to indicate "this task just "finishes" and has no result". If I were to choose, I would definitely choose Void instead of Sendable to express this idea.

huangapple
  • 本文由 发表于 2023年3月23日 09:43:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/75818624.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定