Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mutable variable vs Mutable collection

In my application I need ability to swap elements in collection. So I have a choice:

  1. use mutable collection declared as val
  2. or use immutable collection declared as var (and always reassign new collection to var)

But in Scala (in functional programming) mutability always avoided. So what is less worse: mutable collection declared using val or immutable collection declared as var?

like image 948
WelcomeTo Avatar asked Jul 23 '13 13:07

WelcomeTo


2 Answers

This really depends on whether you need to share that collection widely. The advantage of a mutable collection is that it is usually faster than the immutable collection, and it's easier to have a single object to pass around rather than having to make sure you can set a var from different contexts. But since they can change out from under you, you have to be careful even in a single-threaded context:

import collection.mutable.ArrayBuffer
val a = ArrayBuffer(1,2,3,4)
val i = a.iterator
i.hasNext             // True
a.reduceToSize(0)
i.next                // Boom!

java.lang.IndexOutOfBoundsException: 0
at scala.collection.mutable.ResizableArray$class.apply(ResizableArray.scala:43)
    ...

So if it's going to be widely used, you should consider whether you can be appropriately careful to avoid problems like this. It's generally safer to use a var to an immutable collection; then you might get out of date, but at least you won't fall on your face with a segfault.

var v = Vector(1,2,3,4)
val i = v.iterator
i.hasNext            // True
v = Vector[Int]()
i.next               // 1

Now, however, you have to pass v as a return value from any method that might modify it (outside of the class that contains it, at least). This also can cause problems if you forget to update the original value:

var v = Vector(1,2,3,4)
def timesTwo = v.map(_ * 2)
timesTwo
v       // Wait, it's still 1,2,3,4?!

But then this doesn't update either, does it?:

a.map(_ * 2)    // Map doesn't update, it produces a new copy!

So, as a general rule,

  1. Performance requires you to use one -- use it
  2. Local scope within a method -- use mutable collection
  3. Shared with other threads/classes -- use immutable collection
  4. Implementation within a class, simple code -- use mutable collection
  5. Implementation within a class, complex code -- use immutable

but you should probably violate this as often as you stick to it.

like image 163
Rex Kerr Avatar answered Oct 12 '22 14:10

Rex Kerr


If you use a var holding an immutable collection you can publish it fairly freely (though you may want to mark the var as @volatile). At any given time other code can get only a particular snapshot of that state which can never change.

If you use a val holding a mutable collection instance, then you must guard it carefully, since it can be witnessed in inconsistent states while being updated.

like image 39
Randall Schulz Avatar answered Oct 12 '22 13:10

Randall Schulz