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

时间:2022-07-20 16:37:21

tl;dr

TL;博士

Is it possible to instantiate a generic Swift 4 enum member with an associated value of type Void?

是否可以实例化具有Void类型的关联值的通用Swift 4枚举成员?

Background

背景

I'm using a simple Result enum (similar to antitypical Result):

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

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

Now I'd like to use this enum to represent the result of an operation which does not yield an actual result value; the operation is either succeeded or failed. For this I'd define the type as Result<Void>, but I'm struggling with how to create the Result instance, neither let res: Result<Void> = .success nor let res: Result<Void> = .success() works.

现在我想用这个枚举来表示一个不产生实际结果值的操作的结果;操作成功或失败。为此,我将类型定义为Result ,但我正在努力解决如何创建Result实例,既不让res:Result = .success也不要让res:Result = .success( )工作。

3 个解决方案

#1


39  

In Swift 3 you can omit the associated value of type Void:

在Swift 3中,您可以省略Void类型的关联值:

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

In Swift 4 you have to pass an associated value of type Void:

在Swift 4中,您必须传递Void类型的关联值:

let res: Result<Void> = .success(())
// Or just:
let res = Result.success(())

#2


15  

In Swift 4, an enum case with a Void associated value is no longer equivalent to a an enum case with an empty list of associated values.

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

I believe this is, as Martin says, 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 for Swift 4).

我相信,正如Martin所说,这是SE-0029的结果,你不能再将一个参数元组传递给一个函数并让它们“跨越”参数(尽管该提议已在Swift 3中实现,我相信这个特殊情况后来在Swift 4的SE-0110实施中被采用。

As a result, this means you can no longer call a (Void) -> T as a () -> T in Swift 4. You now have to pass Void in explicitly:

因此,这意味着您不能再在Swift 4中调用(Void) - > T作为() - > T.您现在必须明确地传递Void:

let result = Result.success(())

However, I find this pretty ugly, so I usually implement an extension like this:

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

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

Which lets you say things like this:

这让你说出这样的话:

var result = Result.success
result = .success

It's worth noting that this workaround isn't just limited to enum cases, it can be also used with methods in general. For example:

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

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()

#3


3  

Void is simple typealias for empty tuple: () so you can use it as any of following:

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

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

#1


39  

In Swift 3 you can omit the associated value of type Void:

在Swift 3中,您可以省略Void类型的关联值:

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

In Swift 4 you have to pass an associated value of type Void:

在Swift 4中,您必须传递Void类型的关联值:

let res: Result<Void> = .success(())
// Or just:
let res = Result.success(())

#2


15  

In Swift 4, an enum case with a Void associated value is no longer equivalent to a an enum case with an empty list of associated values.

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

I believe this is, as Martin says, 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 for Swift 4).

我相信,正如Martin所说,这是SE-0029的结果,你不能再将一个参数元组传递给一个函数并让它们“跨越”参数(尽管该提议已在Swift 3中实现,我相信这个特殊情况后来在Swift 4的SE-0110实施中被采用。

As a result, this means you can no longer call a (Void) -> T as a () -> T in Swift 4. You now have to pass Void in explicitly:

因此,这意味着您不能再在Swift 4中调用(Void) - > T作为() - > T.您现在必须明确地传递Void:

let result = Result.success(())

However, I find this pretty ugly, so I usually implement an extension like this:

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

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

Which lets you say things like this:

这让你说出这样的话:

var result = Result.success
result = .success

It's worth noting that this workaround isn't just limited to enum cases, it can be also used with methods in general. For example:

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

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()

#3


3  

Void is simple typealias for empty tuple: () so you can use it as any of following:

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

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