1
votes

I'm trying to extend scala.collection.mutable.Map. I'm looking at https://www.scala-lang.org/api/current/scala/collection/mutable/Map.html . Documentation says class is abstract. Yet I can instantiate a mutable Map like

val m = scala.collection.mutable.Map[Int, Int]()

I'm confused as to what is going on here and how to implement missing methods in my derived class.

1
Because this: scala.collection.mutable.Map[Int, Int]() is not calling a constructor is calling the apply method on the mutable.Map companion object... why do you need / want to extend the Map class? - Luis Miguel Mejía Suárez
I need a fancy update function, something like outlined in this study scastie.scala-lang.org/hyperchessbot/2CBrdmBwSlyfVdIZKnTKuw/27 - hyperbot
And do you really need to override apply? or can you live with just an extension method? And do you need it to be mutable? - Also, BTW, your custom apply looks the Monoid of Map. - Luis Miguel Mejía Suárez
not exactly, I want update to delete the key, if I pass None ( rather than having a value None in the map ), and it actually does this, here is my improved version where I package the whole thing into a case class ( better than nothing, but not real inheritance ) scastie.scala-lang.org/hyperchessbot/2CBrdmBwSlyfVdIZKnTKuw/76 - hyperbot
You didn't add it as part of your question, so I didn't add it to my answer, but you can create such a method: scastie.scala-lang.org/toshetah/39ow51mSRi6g51EtbcjG7Q/1 - Tomer Shetah

1 Answers

1
votes

Please note that Map extends MapFactory.Delegate[Map](HashMap). You can see it Scala source code:

object Map extends MapFactory.Delegate[Map](HashMap) {

In MapFactory.Delegate there is an apply method, which is the one you call (the first method in this class):

class Delegate[C[_, _]](delegate: MapFactory[C]) extends MapFactory[C] {
  override def apply[K, V](elems: (K, V)*): C[K, V] = delegate.apply(elems: _*)
  def from[K, V](it: IterableOnce[(K, V)]): C[K, V] = delegate.from(it)
  def empty[K, V]: C[K, V] = delegate.empty
  def newBuilder[K, V]: Builder[(K, V), C[K, V]] = delegate.newBuilder
}

From your comments, it seems like you want to implement a custom update. You can try this function:

def customUpdate[K](m: mutable.Map[K, Int], key: K, value: Option[Int]): Unit = {
  value.fold {
    m.remove(key)
  } { newValue =>
    m.updateWith(key) {
      case None =>
        Some(newValue)
      case Some(currentValue) =>
        Some(currentValue + newValue)
    }
  }
}

which created the expected output as in your comments. Code run in Scastie.