Swift枚举中通用关联值的确切限制是什么?

alg*_*gal 14 generics enums swift

我试图理解Swift中具有通用关联值的枚举的确切限制.

你可能认为它们是受支持的,因为它Optional是这种类型.这是OptionalSwift标准库中定义的代码:

enum Optional<T> : Reflectable, NilLiteralConvertible {
    case None
    case Some(T)
// ...
}
Run Code Online (Sandbox Code Playgroud)

似乎case成员Some具有变量类型的关联值T,对吧?

但是,在Swift中的函数编程(第87页)一书中提到,不支持这样的类型:

我们想在与Success相关的结果中定义一个通用的新枚举:

enum Result<T> {
    case Success(T)
    case Failure(NSError) 
} 

遗憾的是,当前的Swift编译器不支持通用关联值.

实际上,如果您将该代码段输入编译器,则会出现错误(error: unimplemented IR generation feature non-fixed multi-payload enum layout).

那么这里发生了什么?它只是一般不支持,但Optional作为一个特例支持?有没有办法看看Optional如何获得这种特殊支持?或者,如果其他标准库类型也获得特殊支持?

ric*_*ter 19

在Swift 2中(作为Xcode 7的一部分),对关联值没有限制.所以,随意跳舞,像这样的节拍:

enum YouCanGoWith<T, U> {
    case This(T)
    case That(U)
    case Us
}
Run Code Online (Sandbox Code Playgroud)

现在,如果您正在寻找成功或错误类型的枚举,您可能想停下来思考为什么......因为Swift 2还带来了一个新的错误处理模型.所以你不需要像函数的返回值这样的类型 - 你可以像这样声明它:

func walkWith(rhythm: Bool) throws -> Place { /* ... */ }
Run Code Online (Sandbox Code Playgroud)

...如果你的函数成功,调用者总是得到一个(非可选的)Placewalken to.并且 - 与使用结果分开 - 调用者决定如何处理,吞下或传播错误.

有关详细信息,请参阅Swift编程语言错误处理.仔细观察 - 语法看起来有点像你在其他一些语言中看到的异常模型,但Swift错误是一种完全不同的动物.

(当然,该throws模型特定于同步调用.如果您要声明异步进程的回调,其中回调闭包接收成功异步工作或错误的结果 - 成功或错误类型仍然是完全合适的.)


Rob*_*ier 6

这个答案在Swift 2中已经过时了.请参阅rickster对Swift 2更新的回答.

你的意见是对的.如果其中任何一个具有未知大小,则不能有多个具有关联数据的案例.值类型可以是任何大小(因为它们被复制).引用类型(如对象)具有已知大小,因为它们存储指针.

对此的典型解决方案是创建一个额外的包装类来保存泛型类型,就像FP书一样.每个人都Box按惯例称呼它.有理由希望Swift团队将在未来解决这个问题.如您所知,他们将其称为"未实现"而非"不受支持".

典型的实施方式Box:

final public class Box<T> {
  public let unbox: T
  public init(_ value: T) { self.unbox = value }
}
Run Code Online (Sandbox Code Playgroud)