In Odersky et al's Scala book, they say use lists. I haven't read the book cover to cover but all the examples seem to use val List. As I understand it one also is encouraged to use vals over vars. But in most applications is there not a trade off between using a var List or a val MutableList?. Obviously we use a val List when we can. But is it good practice to be using a lot of var Lists (or var Vectors etc)?
I'm pretty new to Scala coming from C#. There I had a lot of:
public List<T> myList {get; private set;}
collections which could easily have been declared as vals if C# had immutability built in, because the collection itself never changed after construction, even though elements would be added and subtracted from the collection in its life time. So declaring a var collection almost feels like a step away from immutability.
In response to answers and comments, one of the strong selling points of Scala is: that it can have many benefits without having to completely change the way one writes code as is the case with say Lisp or Haskell.
I would say it's better practice to use
var
with immutable collections than it is to useval
with mutable ones. Off the top of my head, becauseYou have more guarantees about behaviour: if your object has a mutable list, you never know if some other external object is going to update it
You limit the extent of mutability; methods returning a collection will yield an immutable one, so you only have mutablility within your one object
It's easy to immutabilize a var by simply assigning it to a val, whereas to make a mutable collection immutable you have to use a different collection type and rebuild it
In some circumstances, such as time-dependent applications with extensive I/O, the simplest solution is to use mutable state. And in some circumstances, a mutable solution is just more elegant. However in most code you don't need mutability at all. The key is to use collections with higher order functions instead of looping, or recursion if a suitable function doesn't exist. This is simpler than it sounds. You just need to spend some time getting to know the methods on List (and other collections, which are mostly the same). The most important ones are:
map
: applies your supplied function to each element in the collection - use instead of looping and updating values in an arrayfoldLeft
: returns a single result from a collection - use instead of looping and updating an accumulator variablefor-yield
expressions: simplify your mapping and filtering especially for nested-loop type problemsUltimately, much of functional programming is a consequence of immutability and you can't really have one without the other; however, local vars are mostly an implementation detail: there's nothing wrong with a bit of mutability so long as it cannot escape from the local scope. So use vars with immutable collections since the local vars are not what will be exported.
Here is how I see this problem of mutability in functional programming.
Best solution: Values are best, so the best in functional programming usage is values and recursive functions:
Need mutable stuff: Sometimes mutable stuff is needed or makes everything a lot easier. My impression when we face this situation is to use the mutables structures, so to use
val list: collection.mutable.LinkedList[T]
instead ofvar list: List[T]
, this is not because of a real improvement on performances but because of mutable functions which are already defined in the mutable collection.This advice is personal and maybe not recommended when you want performance but it is a guideline I use for daily programming in scala.
If it is necessary to use var lists, why not? To avoid problems you could for example limit the scope of the variable. There was a similar question a while ago with a pretty good answer: scala's mutable and immutable set when to use val and var.
I believe you can't separate the question of mutable
val
/ immutablevar
from the specific use case. Let me deepen a bit: there are two questions you want to ask yourself:var
. The reason is that the only way to do so with a mutableval
is through a defensive copy.val
, and return it wrapped through an unmodifiable wrapper (much like whatCollections.unmodifiableList()
does in Java, here is a question where it's asked how to do so in Scala). I see no way to achieve this with an immutable var, so I believe your choice here is mandatory.var
you can directly return the internal representation, so it is slightly clearer maybe.var
a better choice: you can just assign what's in input to your current state, and you are fine already. With an immutableval
, you need to first clear your collection, then copy the new contents in. Definitely worse.trait
only exposing methods for the pointwise manipulation of its status. In this case, a mutableval
may be generally better performance-wise, but in case this is an issue I'd recommend taking a look at Scala's collections performance.You are assuming either the
List
must be mutable, or whatever is pointing to it must be mutable. In other words, that you need to pick one of the two choices below:That is a false dichotomy. You can have both:
So, the question you ought to be asking is how do I do that?, but we can only answer that when you try it out and face a specific problem. There's no generic answer that will solve all your problems (well, there is -- monads and recursion -- but that's too generic).
So... give it a try. You might be interested in looking at Code Review, where most Scala questions pertain precisely how to make some code more functional. But, ultimately, I think the best way to go about it is to try, and resort to Stack Overflow when you just can't figure out some specific problem.