Do two copies of a case class use twice the memory when only one property is changed, or does Scala reuse immutable values on copy to save memory?

Viewed 53

In the following code I instantiate Name once and memory must be allocated to store two strings. I then make a copy of that first object, but only changing one property:

case class Name(first: String, last: String)

val original = Name("Freddie", "Mercury")
val copy = original.copy(first = "Robert")

My question - since last is an immutable val, does Scala point copy.last to the same string in memory as original.last in order to save space?

1 Answers

Name would look something like this in Java (output after compiling and decompiling):

public Name copy(final String first, final String last) {
    return new Name(first, last);
}

public String copy$default$1() {
    return this.first();
}

public String copy$default$2() {
    return this.last();
}

public String first() {
    return this.first;
}

public String last() {
    return this.last;
}

You can see that when you copy a Name object, the default second argument is last()/last, meaning that the last field of the newly created Name is, as you guessed, pointing to the same object as the original Name's last field.

I suppose you could say this is to save the JVM space, but it would also just not make any sense to copy all the fields of a Product instance. copy is not deepCopy, and if you wanted to copy the original object's fields, where would you stop? Do you also copy the fields of those fields, and so on? And how exactly would you copy a field of type Foo without the compiler generating code that does some nasty reflection? It just makes more sense to reuse the fields.

Related