Scala Iterablesでのエクササイズ を実行中に、次の奇妙な動作に遭遇しました。
val xs = Set(5,4,3,2,1)
val ys = Set(1,2,3,4,5)
xs sameElements ys // true
val xs = Set(3,2,1)
val ys = Set(1,2,3)
xs sameElements ys // false - WAT?!
確かにこれらのセットは同じ要素を持ち、順序を無視する必要があります。そして、なぜこれが大きなセットでのみ期待どおりに機能するのですか?
Scalaコレクションライブラリは、5個未満の値のセットに特化した実装を提供します( source を参照)。これらの実装の反復子は要素を返します大きいセットに使用される一貫したハッシュベースの順序ではなく、追加された順序。
さらに、sameElements
( scaladoc )はIterable
sで定義されています(IterableLike
で実装されています- source を参照) ;反復子が同じ要素を同じ順序で返す場合にのみtrueを返します。
そのため、Set(1,2,3)
とSet(3,2,1)
)は同等である必要がありますが、イテレータは異なるため、sameElements
はfalseを返します。
この動作は驚くべきことであり、セットの数学的期待に違反するため、間違いなくバグです(ただし、特定のサイズのセットのみ)。
I.K.としてコメントで指摘しているように、セットを互いに比較しているだけの場合、_==
_は正常に機能します。つまり、Set(1,2,3) == Set(3,2,1)
です。ただし、sameElementsは、2つの反復可能要素の要素を比較できるという点でより一般的です。たとえば、List(1, 2, 3) == Array(1, 2, 3)
はfalseですが、List(1, 2, 3) sameElements Array(1, 2, 3)
はtrueです。
より一般的には、平等は混乱を招く可能性があります-以下に注意してください:
_List(1,2,3) == Vector(1,2,3)
List(1,2,3) != Set(1,2,3)
List(1,2,3) != Array(1,2,3)
Array(1,2,3) != Array(1,2,3)
_