Expand Scala Concrete Type Set

Actually struggling to understand how to extend an immutable set with a class that will be a set of specific types. I am doing this to try to create a good DSL.

I would like to have a Thing class, and when you add β€œthings” together, you get a ThingSet object that extends Set.

class Thing(val name:String){ def +(other: Thing):ThingSet = new ThingSet() + other } 

I just can't figure out how to create a ThingSet object. I know that I need to mix traits like GenericSetTemplate, SetLike, etc. But I just can't get it to work.

Please can someone give me some pointers as I cannot find anything explicit enough to learn. I tried to take a look at the implementations of BitSet and HashSet, but got lost.

0
scala
Dec 11 '10 at 13:17
source share
2 answers

Adaptation from this daily Scala message, as well as the BitSet source, which is a great example here, because it is not a parameterized set, and rather short and simple.

 import scala.collection.SetLike import scala.collection.generic.{GenericSetTemplate, GenericCompanion, CanBuildFrom} import scala.collection.mutable.{Builder, SetBuilder} class ThingSet(seq : Thing*) extends Set[Thing] with SetLike[Thing, ThingSet] with Serializable { override def empty: ThingSet = new ThingSet() def + (elem: Thing) : ThingSet = if (seq contains elem) this else new ThingSet(elem +: seq: _*) def - (elem: Thing) : ThingSet = if (!(seq contains elem)) this else new ThingSet(seq filterNot (elem ==): _*) def contains (elem: Thing) : Boolean = seq exists (elem ==) def iterator : Iterator[Thing] = seq.iterator } object ThingSet { def empty: ThingSet = new ThingSet() def newBuilder: Builder[Thing, ThingSet] = new SetBuilder[Thing, ThingSet](empty) def apply(elems: Thing*): ThingSet = (empty /: elems) (_ + _) def thingSetCanBuildFrom = new CanBuildFrom[ThingSet, Thing, ThingSet] { def apply(from: ThingSet) = newBuilder def apply() = newBuilder } } 
+7
Dec 14 '10 at 1:13
source share

From the skyscrapers to Set, I think you just need to implement 4 or 5 methods. In this case, I decided to use Seq [Thing] support to create my actual implementation.

 class ThingSet(things: Seq[Thing]) extends Set[Thing] { def contains(key: Thing) = { things.contains(key) } def iterator: Iterator[Thing] = { things.iterator } def +(elem: Thing) = new ThingSet(things :+ elem) def -(elem: Thing) = new ThingSet(things.filterNot(_ == elem)) override def empty = new ThingSet(Nil) } class Thing(val name: String) { def +(other: Thing) = { new ThingSet(List(this,other)) } override def toString = name } val thing = new Thing("I'm a new thing") println(thing + new Thing("I'm some other thing")) 

leads to:

 Set(I'm a new thing, I'm some other thing) 

note: I think you should run this in the script file and not in the REPL due to the cyclical dependency between Thing and ThingSet.

+3
Dec 13 '10 at 10:10
source share



All Articles