How to "update" an immutable element in an immutable set in Scala?
I have Set
elements that have their equality defined around the key, but other fields might be different ... So when I need to "update" this is what I tried:
object sandbox {
case class K(val id: Int, val message: String) {
override def equals(that: Any) = that match {
case K(this.id, _) => true
case _ => false
}
override def hashCode = this.id
override def toString = "(" + id + "," + message + ")"
}
val s = Set(K(1, "a"), K(2, "b")) //> s : scala.collection.immutable.Set[test.sandbox.K] = Set((1,a), (2,b))
val updatedElem = K(1, "c") //> updatedElem : test.sandbox.K = (1,c)
s + updatedElem //> res0: scala.collection.immutable.Set[test.sandbox.K] = Set((1,a), (2,b))
Set(updatedElem) | s //> res1: scala.collection.immutable.Set[test.sandbox.K] = Set((1,c), (2,b))
}
Adding an item that already exists won't change the set, and removing it first and adding the updated one again seems kind of suboptimal.
The method union
keeps the elements of the set on the left, but this behavior is not documented; so I shouldn't rely on it.
So, is there something more obvious that I am missing? Should I rely on the actual behavior (and write a test in case it changes)? Or do I need to upgrade in two steps?
source to share
From my point of view, this is actually a problem of modeling concepts. The point is that equal objects must be truly equivalent ... otherwise you might consider some other structures. For example, why not try Map
which one displays id
in message
(or id
in K(id,message)
)? This seems much clearer in concepts and then you can use .updated(1,"c")
to update it.
source to share