我试图了解Swift中具有通用关联值的枚举的确切限制。
您可能认为它们受支持,因为Optional
就是这种类型。以下是Swift标准库中定义Optional
的代码:
enum Optional<T> : Reflectable, NilLiteralConvertible {
case None
case Some(T)
// ...
}
似乎案件成员Some
具有变量类型T
的关联值,对吗?
但是,书Functional Programming in Swift(第87页)中提到,不支持此类型:
我们想要定义一个通用的新枚举 与成功相关的结果:
enum Result<T> { case Success(T) case Failure(NSError) }不幸的是,当前的Swift编译器不支持通用关联值。
事实上,如果您将该代码段输入编译器,则会出现错误(error: unimplemented IR generation feature non-fixed multi-payload enum layout
)。
那么这里发生了什么?它只是一般不支持,但作为特例支持Optional
吗?有没有办法看看Optional如何获得这种特殊支持?或者,如果其他标准库类型也获得特殊支持?
答案 0 :(得分:19)
在Swift 2中(作为Xcode 7的一部分),对关联值没有限制。所以,请随意跳舞,比如:
enum YouCanGoWith<T, U> {
case This(T)
case That(U)
case Us
}
现在,如果您正在寻找成功或错误类型的枚举,您可能想停下来思考为什么......因为Swift 2还带来了一个新的错误处理模型。所以你不需要这样的类型作为你的函数的返回值 - 你可以这样声明:
func walkWith(rhythm: Bool) throws -> Place { /* ... */ }
...如果你的函数成功,调用者总是得到一个(非可选的)Place
用于walken。并且 - 与使用结果分开 - 调用者决定如何处理,吞下或传播错误。
有关详细信息,请参阅 Swift编程语言中的Error Handling。仔细观察 - 语法看起来有点像你在其他语言中看到的异常模型,但Swift错误是一种完全不同的动物。
(当然,throws
模型特定于同步调用。如果您正在声明异步进程的回调,其中回调闭包接收成功异步工作或错误的结果 - 成功 - or-Error类型仍然完全合适。)
答案 1 :(得分:6)
这个答案在Swift 2中已经过时了。请参阅rickster对Swift 2更新的回答。
您的评论是正确的。如果其中任何一个具有未知大小,则您不能拥有多个具有关联数据的案例。值类型可以是任何大小(因为它们被复制)。引用类型(如对象)具有已知大小,因为它们存储指针。
典型的解决方案是创建一个额外的包装类来保存泛型类型,就像FP书一样。按惯例,每个人都称它为Box
。有理由希望Swift团队将来能够解决这个问题。如你所知,他们称之为&#34;未实现&#34;不支持#34;
Box
的典型实现:
final public class Box<T> {
public let unbox: T
public init(_ value: T) { self.unbox = value }
}