javadba javadba - 2 months ago 18
Scala Question

Add element to a Set from the Left (for readability)

Consider adding an element (from the left) to a Sequence using

+:
:

scala> val cl = Seq(1,2,3)
scala> 5 +: cl
res2: Seq[Int] = List(5, 1, 2, 3)


What (if any) is the equivalent for a Set ?

scala> val s = Set(1,2,3)
scala> 5 +: s
<console>:9: error: value +: is not a member of scala.collection.immutable.Set[Int]
5 +: s

scala> 5.toInt + s
<console>:9: error: overloaded method value + with alternatives:
(x: Double)Double <and>
(x: Float)Float <and>
(x: Long)Long <and>
(x: Int)Int <and>
(x: Char)Int <and>
(x: Short)Int <and>
(x: Byte)Int <and>
(x: String)String
cannot be applied to (scala.collection.immutable.Set[Int])
5.toInt + s


Update I am well aware a Set does not retain order. The motivation is for readability of the code in certain cases - specifically when the Set is actually a long computation. The intent is to highlight the new element being added by placing it before that computation.

Answer

Most implementations of Set don't preserve insertion order, so it doesn't make much sense to have such an operation. Of the immutable Sets only ListSet preserves (reverse) insertion order. So since it preserves reverse insertion order, ListSet has a "add to the left" method: the default + method. Yet it still doesn't have a "add to the other side" method.

If you simply want a +: method regardless of what it does, you can just add it as an extension method:

scala> implicit class PrependSet[A](val set: Set[A]) extends AnyVal {
     |   def +:(a: A) = set + a
     | }
defined class PrependSet

scala> 5 +: Set(1,2,3)
res0: scala.collection.immutable.Set[Int] = Set(1, 2, 3, 5)