如何让 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<T, Error>
的原因)。
如果您使用惰性序列,则确定两个序列是否相等是一个非常常见的问题,并且将它们转换为数组是非性能的。 elementsEqual
有效,但没有那么优雅
不如什么优雅?如果您的意思是elementsEqual
,那就是正确的工具。你当然可以在它之上构建额外的工具来表达更复杂的算法,但你不能表达Equatable,因为它有一个特定的含义,而这不是。如果您说set1 == set2
,您希望它执行典型的 Set 的 == 代码,还是希望它运行 elementsEqual(如果您创建了您想要的)?他们返回不同的东西。以上是关于如何让 Sequence 实现 Equatable?的主要内容,如果未能解决你的问题,请参考以下文章
如何根据实现该协议的两个实例的身份为一个协议实现 Equatable 协议?
不恰当Equatable协议==方法的实现对SwiftUI中@State修饰属性的影响