0

I want to create a new custom Scala collection from existing Set Collection which I can later extend with some additional functions.

For the moment, I am trying to make it behave as the standard collection Set. I tried the following link : https://docs.scala-lang.org/overviews/core/custom-collections.html where they have a custom collection that extends on Map. However extending on Set seems a bit different and I am having a ton of type incompatibility that I am not able to resolve.

Here's my starting code : the parts I am not able to define are addOne, substractOne, contains and iterator.

import scala.collection._

class TestSet[A]
  extends mutable.Set[A]
    with mutable.SetOps[A, mutable.Set, TestSet[A]] {

  override def empty: TestSet[A] = new TestSet

  // Members declared in scala.collection.mutable.Clearable
  override def clear(): Unit = immutable.Set.empty

  // Members declared in scala.collection.IterableOps
  override protected def fromSpecific(coll: IterableOnce[A]): TestSet[A] = TestSet.from(coll)

  override protected def newSpecificBuilder: mutable.Builder[A, TestSet[A]] = TestSet.newBuilder

  override def className = "TestSet"

  //override def subtractOne(elem: A): TestSet.this.type = ???

  //override def addOne(elem: A): TestSet.this.type = ???

  //override def contains(elem: A): Boolean = ???

   //override def iterator: Iterator[A] = {
   //}
}

object TestSet {
  def empty[A] = new TestSet[A]


  def from[A](source: IterableOnce[A]): TestSet[A] =
    source match {
      case pm: TestSet[A] => pm
      case _ => (newBuilder ++= source).result()
    }

  def apply[A](elem: A*): TestSet[A] = from(elem)

  def newBuilder[A]: mutable.Builder[A, TestSet[A]] =
    new mutable.GrowableBuilder[A, TestSet[A]](empty)

  import scala.language.implicitConversions

  implicit def toFactory[A](self: this.type): Factory[A, TestSet[A]] =
    new Factory[A, TestSet[A]] {
      def fromSpecific(it: IterableOnce[A]): TestSet[A] = self.from(it)

      def newBuilder: mutable.Builder[A, TestSet[A]] = self.newBuilder
    }


}
Usr654789
  • 47
  • 6
  • 4
    If you don't know how to implement those functions, how do you even expect to create a new collection at all? Like those are the very fundamental operations that define a `mutable.Set` - Let me ask the question in another way, what was exactly the meta-problem you wanted to solve? What do you mean with _"which I can later extend with some additional functions"_? - It seems to me that rather than creating a new collection, you just want to have a small utility class that wraps an existing collection adding extra functions; actually such class may be a custom collection but that is not necessary – Luis Miguel Mejía Suárez Dec 24 '22 at 01:58
  • 1
    You may also evaluate if all you need is just defining extension methods to existing collections. – Luis Miguel Mejía Suárez Dec 24 '22 at 01:58
  • @LuisMiguelMejíaSuárez I am not here to grade my abilities my friend, I am not skilled in programming and I am already seeking help here. Yes I am trying to wrap the existing Set collection with a small utility class that I might change its implementation later. I still want to benefit from the standard functions like "collect" and "filter" without re-implementing them since this class will replace the use of standard Set in a project with minimum change. – Usr654789 Dec 24 '22 at 02:09
  • 1
    Then, as suggested by Luis, look at extension method. They are there exactly for that: take an existing type/implementation and enrich it with 'ew methods. – Gaël J Dec 24 '22 at 07:23
  • 1
    @Usr654789 what kind of utilities do you want your new class to have? Right now is really not possible to answer your question in a concrete way, only giving vague ideas. – Luis Miguel Mejía Suárez Dec 24 '22 at 14:44
  • @LuisMiguelMejíaSuárez I updated the question. About the utilities, something like my own version of set union, disjoint union,... Have a private Hashmap that is equivalent to set set and evolve with it and where I can choose to work on the map instead of the set. I apologize for my relatively bad expression or terminology. – Usr654789 Jan 04 '23 at 15:57
  • 1
    @Usr654789 sorry for the delay, I would suggest accepting this answer and opening a new question showing the code that you have right now and what problem are you facing; past the literal compiler error, or even better paste an **Scastie** link. - You may also link this question. – Luis Miguel Mejía Suárez Jan 05 '23 at 14:29
  • @Usr654789 I agree with LMS' comment above. I think I could be able to help you with the new/follow-up question that you edited into the original question, but I'd prefer to do that as a new answer to a new question (instead of editing a 2nd answer to a different question into my original answer). – MartinHH Jan 05 '23 at 17:04
  • @MartinHH,Luis Thank you both, I already accepted the answer and will start a new question. – Usr654789 Jan 05 '23 at 17:13
  • @Usr654789 usually, a green checkmark would appear next to the answer (below the "vote count") after you accepted it, so I think you did not actually accept it yet. – MartinHH Jan 05 '23 at 19:00

1 Answers1

2

I will interpret your question as "I want to do something similar as the Map-example from https://docs.scala-lang.org/overviews/core/custom-collections.html for a mutable Set but now am stuck with this code" and will try to answer that (ignoring any other aspects of your question).

What you need to understand is that mutable.Set and mutable.SetOps are just traits that provide some reusable parts of implementation, but they do not contain any actual data structures.

So if you want to implement your own implementation, you will have to provide the actual underlying data structure yourself (similar to how the PrefixMap from that link has private var suffixes and private var value).

For example, you could use an underlying immutable Set like this:

class TestSet[A]
  extends mutable.Set[A]
    with mutable.SetOps[A, mutable.Set, TestSet[A]] {

  // the underlying data structure
  private var data = mutable.Set.empty[A]

  // ATTENTION: your implementation was different and buggy
  override def clear(): Unit = {
    data = mutable.Set.empty
  }

  override def subtractOne(elem: A): TestSet.this.type = {
    data = data - elem
    this
  }

  override def addOne(elem: A): TestSet.this.type = {
    data = data + elem
    this
  }

  override def contains(elem: A): Boolean = data.contains(elem)

  override def iterator: Iterator[A] = {
    data.iterator
  }
  
  // ...
}

Note that the above is just an example of what you could do in order to get your code to work - I'm not saying that it's a good idea.

MartinHH
  • 982
  • 4
  • 7