如何在 Swift 中解开任意深度嵌套的选项? [英] How to unwrap arbitrarily deeply nested optionals in Swift?

查看:26
本文介绍了如何在 Swift 中解开任意深度嵌套的选项?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

作为 Swift 中的一个练习,我正在尝试编写一个扩展方法来解开任意深度嵌套的选项.这几乎没有实际用途,只是对 Swift 类型系统的探索.

As an exercise in Swift, I am trying to write an extension method that will unwrap arbitrarily deeply nested optionals. This has little practical use and is simply an exploration of Swift's type system.

任意深度嵌套的可选选项的示例是 Optional>>Optional>>>.

Examples of arbitrarily deeply nested optionals are Optional<Optional<Optional<Int>>> and Optional<Optional<Optional<Optional<Int>>>>.

我发现这样做的唯一方法是使用类型擦除:

The only way I've discovered to do this is to use type erasure:

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 类型:

This works well. We can unwrap a deeply nested optional, but unfortunately we have to restate the Wrapped type:

let x = Optional<Optional<Optional<Int>>>(3)
let y = x.unwrap(Int.self)

如果没有类型擦除,我想不出任何方法来做到这一点.一旦你使用了类型擦除,你必须重新声明类型才能恢复它.我不要这个.更精通 Swift 的人能否让我知道这无法完成,或者是否有其他方法?

I can't think of any way to do this without type erasure. And once you use type erasure, you must restate the type to get it back. I don't want this. Can someone more versed in Swift let me know either that this cannot be done or whether there is another way?

推荐答案

这里有一个解决方案,提供高达六级的扁平化Optional:

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
    }
}

上述解决方案的优点是类型安全,缺点是它是静态类型的(例如不能在 Anyflatten()> 变量),并且如果您需要支持越来越多的嵌套级别,则需要添加越来越多的重载.

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.

这篇关于如何在 Swift 中解开任意深度嵌套的选项?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆