Seq class is mutable. Yes, you read that right. I think it’s an extremely important thing to be aware of, and I’m not sure it’s known widely enough. I’ve encountered experienced Scala devs that did not know this.
A word of caution: the default
Seqtypes in scope – defined in
scala.package– are the
scala.collectionversions, as opposed to
Set– defined in
Predef.scala– which are the
scala.collection.immutableversions. This means that, for example, the default
Seqtype can be both the immutable and mutable implementations. Thus, if your method relies on a collection parameter being immutable, and you are using
Seq, you must specifically require/import the immutable variant, otherwise someone may pass you the mutable version.
Within your own code this isn’t a huge problem, though you could certainly shoot yourself in the foot by not realizing this. It becomes much more of an issue when designing APIs. If your API accepts a
Seq, and you need it to be immutable, say for thread-safety concerns or “purity”, then unless you specifically import
scala.collection.immutable.Seq, your function will accept both
scala.collection.mutable.Seq and the immutable variant. It will leak mutability into an otherwise immutable interface.
I’ve seen multiple, fairly large, code bases which use
Seqs all around, assuming they’re immutable, but without specifically importing the immutable version. Just take a look at any Scala library on GitHub, and search for
Seq. You’ll see that most of them just use the default one in scope.
Say you identify this issue and decide you want to start using the immutable version. You might think: “Hey, I’ll just import the immutable version and be done with it”. Doing so, you’ll quickly realize that this requires massive changes to so many source files – you’ll be surprised how many files you’ll need to change to switch to the immutable variant. Every class that has
Seq written in it will require the
So what should you do? You should build your application from the ground-up using
scala.collection.immutable.Seq everywhere applicable. It might feel boilerplate-y to do so, but trust me – you’ll thank yourself down the road.
Why does Scala default to
collection.Seq instead of
immutable.Seq? It is required for working with
varargs. If you’re interested, there’s a lengthy discussion about it on the Scala mailing list which includes Martin Odersky, Jonas Bonér, Paul Phillips, Daniel Spiewak and others weighing in.