具有 Void 关联类型的通用 Swift 4 枚举

Generic Swift 4 enum with Void associated type

tl;dr

是否可以实例化一个泛型 Swift 4 枚举成员与类型 Void 的关联值?

背景

我正在使用一个简单的 Result 枚举(类似于 antitypical Result):

enum Result<T> {
  case success(T)
  case error(Error?)
}

现在我想用这个枚举来表示一个不产生实际结果值的操作的结果;操作是成功失败。为此,我将类型定义为 Result<Void>,但我正在努力创建结果实例,let res: Result<Void> = .successlet res: Result<Void> = .success() 都不起作用。

在Swift3中可以省略类型Void:

的关联值
let res: Result<Void> = .success()

在 Swift 4 中,您必须传递类型为 Void:

的关联值
let res: Result<Void> = .success(())
// Or just:
let res = Result.success(())

Void 是空元组的简单类型别名:() 因此您可以将其用作以下任何一种:

let res1: Result<Void> = .success(())
let res2 = Result<Void>.success(())
let res3 = Result.success(() as Void)
let res4 = Result.success(())

在 Swift 4 中,具有 Void 关联值的枚举案例不再等同于具有空关联值列表的枚举案例。

我相信这是 , a result of SE-0029 where you can no longer pass a tuple of arguments to a function and have them "splat" across the parameters (although the proposal was marked implemented in Swift 3, I believe this particular case was picked up later in the implementation of SE-0110 为 Swift 4).

因此,这意味着您不能再将 (Void) -> T 调用为 Swift 中的 () -> T 4. 您现在必须显式传递 Void

let result = Result.success(())

但是,我觉得这很丑陋,所以我通常会实现这样的扩展:

extension Result where Success == Void {
    static var success: Result {
        return .success(())
    }
}

这让你可以这样说:

var result = Result.success
result = .success

值得注意的是,此解决方法不仅限于枚举情况,它还可以与一般方法一起使用。例如:

struct Foo<T> {
  func bar(_ a: T) {}
}

extension Foo where T == Void {
  func bar() { bar(()) }
}

let f = Foo<Void>()

// without extension:
f.bar(())

// with extension:
f.bar()

Swift 5 已将结果更新为需要 Failure 参数,但仍需要相关值:

let res: Result<Void, Error> = .success(())

我发现 .success(Void()) 更具描述性和简单性。