首页 > 解决方案 > 如何在 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 的人告诉我这无法完成或是否有其他方法?

标签: swiftswift4

解决方案


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.


推荐阅读