如何让 Sequence 实现 Equatable?

Posted

技术标签:

【中文标题】如何让 Sequence 实现 Equatable?【英文标题】:How can I get Sequence to implement Equatable? 【发布时间】:2019-03-18 23:24:16 【问题描述】:

我有以下最佳尝试:

extension Equatable where Self: Sequence, Self.Element: Equatable 
    public static func == (lhs: Self, rhs: Self) -> Bool 
        return lhs.elementsEqual(rhs)
    

但它似乎不起作用。此外,它要求两个序列具有相同的确切类型,而我只想限制它们的 Element 类型相同。有没有办法做到这一点?

【问题讨论】:

请注意,两个相等的序列并不意味着 elementsEqual - 例如,两个相等的 Set 值可能包含相同的元素但顺序不同,这会使 elementsEqual 返回 false。 【参考方案1】:

协议从不符合其他协议。协议可以要求其他协议(我们通常称之为“协议继承”),但这并不能使协议符合其他协议。协议甚至不符合自身,更不用说其他东西了。 Sequence.self 不能传递给需要 Sequence.Type 的东西。

在任何情况下,Equatable 都要求被比较的事物属于同一类型。 "equal" 的其他含义不是 Equatable。

如果您想在“这两个序列具有相同的元素”之上构建方法,那很好。这就是elementsEqual 已经为您所做的。但这并不能使它们平等。

您正在尝试构建什么算法来使用它而 elementEqual 尚未处理?

您正在寻找的可能只是一些语法糖,使其看起来像==。这完全没有问题。你可以构建任何你想实现的操作符elementsEqual

infix operator ~=

func ~= <S1, S2>(lhs: S1, rhs: S2) -> Bool
    where S1: Sequence, S2:Sequence,
    S1.Element: Equatable, S1.Element == S2.Element

    return lhs.elementsEqual(rhs)

我通常建议不要使用自定义运算符,但如果您正在做大量此类工作,那么明确的“这些序列在相同的顺序中具有相同的值”运算符可能会非常有用。您只是不想使用==,因为这已经意味着这并不意味着。例如,两个Set可能是==,但不是~=,所以你需要选择你所指的工具。

【讨论】:

有点吹毛求疵:一些协议符合自己,例如 @objc 没有静态要求的协议,最近在 Swift 5 中,Error 符合自己(这是允许 Result&lt;T, Error&gt; 的原因)。 如果您使用惰性序列,则确定两个序列是否相等是一个非常常见的问题,并且将它们转换为数组是非性能的。 elementsEqual 有效,但没有那么优雅 不如什么优雅?如果您的意思是elementsEqual,那就是正确的工具。你当然可以在它之上构建额外的工具来表达更复杂的算法,但你不能表达Equatable,因为它有一个特定的含义,而这不是。如果您说set1 == set2,您希望它执行典型的 Set 的 == 代码,还是希望它运行 elementsEqual(如果您创建了您想要的)?他们返回不同的东西。

以上是关于如何让 Sequence 实现 Equatable?的主要内容,如果未能解决你的问题,请参考以下文章

如何根据实现该协议的两个实例的身份为一个协议实现 Equatable 协议?

为自定义私有类实现 Equatable - Swift

如何比较两个实际符合“Equatable”的“Any”对象

不恰当Equatable协议==方法的实现对SwiftUI中@State修饰属性的影响

不恰当Equatable协议==方法的实现对SwiftUI中@State修饰属性的影响

如何使用 Equatable 创建扩展以删除自定义数组元素?