Reputation: 66430
I learned today that scala's Seq
can mean that both a mutable or immutable Seq can fulfill its type alias. (I stumbled over a blogpost talking about it.)
In my codebase, I try to follow functional programming best practices and while I did assume Seq
to enforce an immutable Sequence, it may not be and hence causing an entry-point for unintended side-effects.
In order to protect against mutable Seq I could type my functions using a Sequence with:
scala.collection.immutable.Seq
in each of my files in which I am expecting a Seq
.
I also do not prefer to read immutable.Seq
in my code base.
For me, Seq
should behave just like Set
alias and be immutable by default.
Is there a way I can make the default Seq
alias to point to its immutable counterpart for my project without hindering vendor imports?
Upvotes: 2
Views: 5119
Reputation: 51271
OK, having read the (4-year old) blog post, I really don't see this as being much of an issue.
The default Seq()
is collection.Seq
which isn't mutable itself, but it is the parent of both the mutable and immutable variants. So code that creates and passes default Seq
collections isn't effected but code that accepts a Seq
parameter might receive a mutable.Seq
. But that's only an issue if immutability is not just assumed but required, e.g. for thread safety.
Bottom line: Put an import collection.immutable.Seq
at the top of those files where:
Seq
, andUpvotes: 3
Reputation:
I wouldn't recommend trying to mess with default Scala behaviour. Unless you define your own function which takes any input and returns an immutable Seq of that input, I think it'd be safest to just use immutable.Seq
You can always try something like this (not thoroughly tested):
def seq(inputs: Any*): scala.collection.immutable.Seq[Any] = {
scala.collection.immutable.Seq(inputs)
}
scala> seq("hi", true)
res0: scala.collection.immutable.Seq[Any] = List(WrappedArray(hi, true))
scala> seq(1, 'c', "string", false)
res1: scala.collection.immutable.Seq[Any] = List(WrappedArray(1, c, string, false))
Edit:
As jwvh pointed out, this option isn't ideal. Using generic types like James Whiteley suggested could be better if you insist on making your own function:
def seq[T](inputs: T*): scala.collection.immutable.Seq[T] =
scala.collection.immutable.Seq(inputs).flatten
This outputs:
scala> seq("hi", true)
res0: scala.collection.immutable.Seq[Any] = List(hi, true)
But I'll reiterate - it might just be best to use immutable.Seq
where needed, or find another collection type to use.
Upvotes: 1