-2

I have a simple usage of var variable with immutable.ListMap type. Unfortunately a code complexity of a project does not give me a chance to move it to immutable val

On review I am getting a comment to change it to var variable with mutable.ListMap. Like "you already have var and mutable won't make thing worse."

What do you think about that? Are there any performance metrics or code style that prohibits using of mutable vars? What is really better to choose between mutable var and immutable var?

I have read all answers for

val-mutable versus var-immutable in Scala and noticed one comment that got lot of likes:

Prefer immutable val over immutable var over mutable val over mutable var

Are there any proofs or explanation for that statement?

  • Why would you change it a `mutable var`? I mean, do you need to change the reference of the object _(var)_ or mutate the object itself _(mutable)_? If you really need both, I would suggest to carefully review the design of the code. Why? Because the more you expose mutations, more easy is to break things, and harder to reason about the code. If you really need mutability for any reason, then aim to keep it closed to the minimum possible scope. – Luis Miguel Mejía Suárez Mar 28 '19 at 18:21
  • No, I do not need both, I am just thinking of a good answer on review that double mutability is a bad idea. – Andrew Kuleshov Mar 28 '19 at 19:05

2 Answers2

1

var with mutable collection is a double mutability.

var mm : scala.collection.mutable.xxx = ???

This means that the collection mm holds can and might change over time and/or mm itself can be changed to reference a completely different collection.

Mutable collections are, occasionally, useful. Mutable variables are seldom needed and should be avoided. Mutable variables typed to mutable collections? I just don't see how that can be justified.

jwvh
  • 50,871
  • 7
  • 38
  • 64
1

ListMap is a good example actually, because, in multithreaded environment, you have to synchronize even when you only look at it. var assignments on the other hand are atomic, you don't need to synchronize at all, just mark it as @volatile.

This is a performance benefit, as well as reliability (whenever your stuff needs synchronized access, it is only a matter of time before someone forgets to code it properly).

So, yes, if you can't use "immutable val" for some reason, then definitely prefer "immutable var" over "mutable val", unless there is an explicit and concrete reason why you require your container to be mutable (e.g., the map is really huge and often updated, causing measurable performance problems).

As for "mutable var", yeah, like the other answer mentioned, I also have no idea why in the world you want to have that.

Dima
  • 39,570
  • 6
  • 44
  • 70
  • Using `volatile` makes assignment atomic (at significant performance cost) but you may still need to synchronise access to your data structures, even immutable ones. – Tim Mar 28 '19 at 22:19
  • Performance cost is real, but not as significant as that of synchronization. No, you don't need to synchronize access to immutable structures. – Dima Mar 29 '19 at 10:57
  • Immutability does not guarantee thread safety because immutable objects can have mutable state that is not thread safe. See [this question](https://stackoverflow.com/questions/41934690/are-scala-immutable-collections-thread-safe). – Tim Mar 29 '19 at 11:03
  • The answer to the question you referenced, says that it is thread safe :D. And it actually _is_. "Exchange values between threads through a volatile var" - is _exactly_ what we are talking about here. – Dima Mar 29 '19 at 11:10
  • Immutable objects cannot have mutable state, that's an oxymoron. They can use mutable state _during construction_ (as that doc states), but that's inconsequential. Once the (immutable) object is created, it is safe. – Dima Mar 29 '19 at 11:38
  • Immutability is a property of the interface, not the implementation. For example an object may store memoized values of previous invocations which requires mutable state but retains the immutability of the interface. Any object which contains a `lazy` value fits into this category. You should never assume that an immutable object is thread safe. – Tim Mar 29 '19 at 11:46
  • It is _possible_ to make an immutable object unsafe. But, if you do that, it is just a bug in your implementation. We are talking about scala standard library here, and I challenge you to find one immutable object there, that is not thread safe, because of mutable state, it somehow uses internally, outside of construction time. And no, `lazy` values are safe. – Dima Mar 29 '19 at 11:56
  • Sigh. "You should not assume that an object with an immutable interface is thread safe" OK? – Tim Mar 29 '19 at 12:13
  • 1
    Nope. You actually _should_ assume that (at least as much as you should assume, that a function called `reasUser` does not write the contents of you /etc/passwd into a socket). And if you ever run into an instance where it does not hold, you should file a bug. – Dima Mar 29 '19 at 12:13
  • As for your challenge, the documentation for `immutable.List` says "the implementation [...] can lead to race conditions in some multi-threaded scenarios" and "an unsynchronized non-volatile read from another thread may observe the object in an invalid state. Note that such a read is not guaranteed to *ever* see the written object at all". [Emphasis added] – Tim Mar 30 '19 at 09:37
  • @Tim the "challenge" specifically mentioned _outside of construction_. – Dima Mar 30 '19 at 11:52