简体   繁体   中英

When is one Set less than another in Scala?

I wanted to compare the cardinality of two sets in Scala. Since stuff sometimes "just work" in Scala, I tried using < between the sets. It seems to go through, but I can't make any sense out of the result.

Example:

scala> Set(1,2,3) < Set(1,4)
res20: Boolean = true
  • What does it return?
  • Where can I read about this method in the API?
  • Why isn't it listed anywhere under scala.collection.immutable.Set ?

Update: Even the order (??) of the elements in the sets seem to matter:

scala> Set(2,3,1) < Set(1,3)
res24: Boolean = false

scala> Set(1,2,3) < Set(1,3)
res25: Boolean = true

This doesn't work with 2.8. On Scala 2.7, what happens is this:

scala.Predef.iterable2ordered(Set(1, 2, 3): Iterable[Int]) < (Set(1, 3, 2): Iterable[Int])

In other words, there's an implicit conversion defined on scala.Predef , which is "imported" for all Scala code, from an Iterable[A] to an Ordered[Iterable[A]] , provided there's an implicit A => Ordered[A] available.

Given that the order of an iterable for sets is undefined, you can't really predict much about it. If you add elements to make the set size bigger than four, for instance, you'll get entirely different results.

If you want to compare the cardinality, just do so directly:

scala> Set(1, 2, 3).size < Set(2, 3, 4, 5).size
res0: Boolean = true

My knowledge of Scala is not extensive, but doing some test, I get the following:

scala> Set(1,2) <
<console>:5: error: missing arguments for method < in trait Ordered;
follow this method with `_' if you want to treat it as a partially applied function
   Set(1,2) <
            ^

That tells me that < comes from the trait Ordered . More hints:

scala> Set(1,2) < _
res4: (Iterable[Int]) => Boolean = <function>

That is, the Set is evaluated into an Iterable , because maybe there is some implicit conversion from Iterable[A] to Ordered[Iterable[A]], but I'm not sure anymore... Tests are not consistent. For example, these two might suggest a kind of lexicographical compare:

scala> Set(1,2,3) < Set(1,2,4)
res5: Boolean = true

1 is equal, 2 is equal, 3 is less than 4.

scala> Set(1,2,4) < Set(1,2,3)
res6: Boolean = false

But these ones don't:

scala> Set(2,1) < Set(2,4)
res11: Boolean = true

scala> Set(2,1) < Set(2,2)
res12: Boolean = false

I think the correct answer is that found in the Ordered trait proper: There is no implementation for < between sets more than comparing their hashCode:

It is important that the hashCode method for an instance of Ordered[A] be consistent with the compare method. However, it is not possible to provide a sensible default implementation. Therefore, if you need to be able compute the hash of an instance of Ordered[A] you must provide it yourself either when inheiriting or instantiating.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM