[英]What's the exact limitation on generic associated values in Swift enums?
我试图理解Swift中具有通用关联值的枚举的确切限制。
您可能认为它们受支持,因为Optional
是这样的类型。 以下是在Swift标准库中定义Optional
的代码:
enum Optional<T> : Reflectable, NilLiteralConvertible {
case None
case Some(T)
// ...
}
看起来像case成员Some
有一个变量类型T
的关联值,对吗?
但是, 在Swift中的函数编程 (第87页)一书中提到,不支持这样的类型:
我们想在与Success相关的结果中定义一个通用的新枚举:
枚举结果<T> {\n 案例成功(T)\n 案例失败(NSError) \n }遗憾的是,当前的Swift编译器不支持通用关联值。
事实上,如果您将该片段输入编译器,则会出现错误( error: unimplemented IR generation feature non-fixed multi-payload enum layout
)。
那么这里发生了什么? 它只是一般不支持,但作为特殊情况支持Optional
吗? 有没有办法看看Optional如何获得这种特殊支持? 或者,如果其他标准库类型也获得特殊支持?
在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
用于向沃肯。 并且 - 与使用结果分开 - 调用者决定如何处理,吞下或传播错误。
有关详细信息,请参阅Swift编程语言中的 错误处理 。 仔细观察 - 语法看起来有点像你在其他一些语言中看到的异常模型,但Swift错误是一种完全不同的动物。
(当然, throws
模型特定于同步调用。如果你要声明异步进程的回调,回调闭包接收成功异步工作或错误的结果 - 成功或错误类型仍然完全适当。)
这个答案在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 }
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.