Data sharing when having var members in case class

In Functional programminag in scala I have read about data sharing:

When we add an element 1 to the front of an existing list, say xs , we return a new list, in this case Cons(1,xs) . Since lists are immutable, we don’t need to actually copy xs ; we can just reuse it. This is called data sharing.

But does it still hold when we have case classes with var members or then we have to copy the whole structure?

If you have something like this:

final class Box(var data: Int) {
  def modify(): { += 1

val boxes = List.tabulate(0, 10)(i => new Box(i))

And then you do this:

val myBoxes = (new Box(100)) :: boxes
myBoxes.foreach(box => box.modify())

Then it is still true that myBoxes.tail is equal to boxes, because for mutable values the only sensible definition of equality is reference equality.

1 Like

While the language allows it, you really, really should never have vars in case classes. Technically, case classes are permitted to do all sorts of things, but in practice their design in focused on immutable data structures. As soon as you permit mutability, almost everything interesting and useful about case classes turns out to be more or less broken.

So I would urge you: just don’t do it. If you need mutability, use traditional classes, not case classes – mutability in case classes is a recipe for confusion and bugs.


so when I copy tail of list these are the same objects no matter if they are class or case class?

I wonder if in this case

sealed trait List[A]
case class Cons[A](var head: A, tail: List[A]) extends List[A]

getting tail not only dont copy A objects but also dont copy Cons structure.
Does it copy Cons structure when there is no var?
Thank You!

Sorry, not sure what you mean.

Especially since we do not copy the tail of a List, we simply reuse them.
The definition of List is:

sealed trait List[+A] extends Product with Serializable
final case class ::[+A](head: A, tail: List[A]) extends List[A]
final case object Nil extends List[Nothing]

So as you can see a cons take a List for its tail, so in my previous example:

val myBoxes = (new Box(100)) :: boxes

Here, we are not copying boxes we are reusing boxes.

Again, sorry, not sure what you mean.

However, as Justin said using vars with case classes simply do not make sense.