swift - 如何在 Swift 中解开任意深度嵌套的选项?
问题描述
作为 Swift 中的一个练习,我正在尝试编写一个扩展方法,该方法将解开任意深度嵌套的选项。这几乎没有什么实际用途,只是对 Swift 类型系统的探索。
任意深度嵌套的选项的示例是Optional<Optional<Optional<Int>>>
和Optional<Optional<Optional<Optional<Int>>>>
。
我发现这样做的唯一方法是使用类型擦除:
protocol TypeErasedOptional {
func deeplyUnwrap() -> Any?
}
extension Optional: TypeErasedOptional {
func deeplyUnwrap() -> Any? {
switch self {
case .none: return nil
case .some(let wrapped as TypeErasedOptional): return wrapped.deeplyUnwrap()
case .some(let wrapped): return wrapped
}
}
func unwrap<T>(_ type: T.Type = T.self) -> T? {
switch deeplyUnwrap() {
case .none: return nil
case .some(let wrapped as T): return wrapped
default: return nil
}
}
}
这很好用。我们可以解开一个深度嵌套的可选项,但不幸的是我们必须重新声明Wrapped
类型:
let x = Optional<Optional<Optional<Int>>>(3)
let y = x.unwrap(Int.self)
如果没有类型擦除,我想不出任何方法来做到这一点。一旦你使用类型擦除,你必须重述类型以取回它。我不想要这个。是否可以让更精通 Swift 的人告诉我这无法完成或是否有其他方法?
解决方案
Here's a solution that provides flattening up to a six-levels Optional
:
extension Optional {
func flatten() -> Wrapped? {
return self
}
func flatten<T>() -> T? where Wrapped == T? {
return map { $0.flatten() } ?? nil
}
func flatten<T>() -> T? where Wrapped == T?? {
return map { $0.flatten() } ?? nil
}
func flatten<T>() -> T? where Wrapped == T??? {
return map { $0.flatten() } ?? nil
}
func flatten<T>() -> T? where Wrapped == T???? {
return map { $0.flatten() } ?? nil
}
func flatten<T>() -> T? where Wrapped == T????? {
return map { $0.flatten() } ?? nil
}
}
The advantage of the above solution is the fact that is type safe, the disadvantages are the fact that it's statically typed (e.g. can't call flatten()
on Any
variables), and that you need to add more and more overloads if you need to support more and more nesting levels.
推荐阅读
- flutter - 如何使用列表视图构建器将检索到的数据从表单页面构建到另一个页面
- java - Opencsv - 如何仅在双引号之外获取用逗号分隔的值,同时忽略双引号?
- c# - 表单提交给 Action 时模型为空
- android - 毕加索图像加载 https 与自签名证书
- php - php中允许的最大文件大小复制功能是什么
- node.js - Mongodb插入50M文档而不重复的最佳方法
- reactjs - ESLint 发现了一个赋值或函数调用,而是在 void 函数上看到了一个表达式
- microservices - 事件驱动架构中的通用事件
- javascript - 如何验证此多步骤表单
- c# - MVC 中的管理员和用户登录