Swift 集合 API:使用计算变量扩展:类型错误

Swift Collection API: extend with a computed variable: type error

我有以下方法:

private func returnNilIfEmpty<T: Collection>(_ collection: T?) -> T? {
    guard let collection = collection else { return nil }
    return collection.isEmpty ? nil : collection
}

我想扩展 Collection API 以使用计算变量来提取非空值,如下所示:

extension Collection {
    var nonEmptyValue: Collection? {
        returnNilIfEmpty(self)
    }
}

但是,我收到错误消息:

Protocol 'Collection' can only be used as a generic constraint because it has Self or associated type requirements

这很清楚,因为外部 Collection 可以是任何集合(例如 [Int]),而 returnNilIfEmpty 内部的集合可以是例如String.

问题是如何执行 Collection 通过 nonEmptyValue 返回的规则和通过 returnNilIfEmpty 返回的相同类型的规则,以便我可以摆脱这个编译器错误?

使用 Self 解决了问题,因为它指向集合的具体类型:

import Foundation

extension Collection {
    var nonEmptyValue: Self? {
        returnNilIfEmpty(self)
    }
}

func returnNilIfEmpty<T: Collection>(_ collection: T?) -> T? {
    guard let collection = collection else { return nil } // nil -> return nil
    return collection.isEmpty ? nil : collection // return nil if empty
}

进一步简化:

import Foundation

extension Collection {
    ///
    var nonEmptyValue: Self? {
        self.isEmpty ? nil : self
    }
}

这里用Self比较合适:

extension Collection {
    var nonEmptyValue: Self? {
        returnNilIfEmpty(self)
    }
}

如果例如你做了 Set([1,2,3]).nonEmptyValue,你期望得到一个 Set<Int>? 而不是一般的 Collection? (你甚至不知道这个类型包含什么样的元素或类似的东西!),你不会吗?