Unmodifiable view of a mutable Scala collection
scala, scala-collections
Solution
The Scala collection library is oriented to immutability, and immutability doesn't refer only to the fact that you are not allowed to modify a given collection, but also that you are guaranteed that the collection won't be ever modified by anyone.
So you cannot and you shouldn't get a collection like immutable.Seq as a view from a mutable buffer in Scala since it breaks that guarantee.
But you can implement the concept of unmodifiable mutable Seq easy enough like so:
class UnmodifiableSeq[A](buffer: mutable.Seq[A]) extends mutable.Seq[A]{
def update(idx: Int, elem: A) {throw new UnsupportedOperationException()}
def length = buffer.length
def apply(idx: Int) = buffer(idx)
def iterator = buffer.iterator
}
Usage:
val xs = Array(1, 2, 3, 4)
val view = new UnmodifiableSeq(xs)
println(view(2)) >> 3
view(2) = 10 >> Exception in thread "main" java.lang.UnsupportedOperationException
EDIT :
A probably better way of obtaining an unmodifiable view of the collection is by downcasting to `collection.Seq` which provides no mutable update operations:
val xs = Array(1, 2, 3)
val view: Seq[Int] = xs //this is unmodifiable
or creating a wrapper which extends `Seq` if you have your own custom mutable class.
class UnmodifiableView[A](col: MutableCollection[A]) extends collection.Seq[A]{
def length = col.length
def apply(idx: Int) = col(idx)
def iterator = col.iterator
}
The `scala.collection.Seq` trait does not make any guarantees of immutability but it also does not allow any modifying operations so it seems the perfect fit.
Problem
I have a class with a private field that is a mutable collection. The field in this particular instance is an `ArrayBuffer`, although my question extends to any finite, ordered, random-access collection type. I want to expose this field without permitting others to modify it. In Java I would add a method like: ``` private List<T> theList; public List<T> getList() { return Collections.unmodifiableList(theList); } ``` In Java we just accept that the result is a `List` that doesn't fully implement the `List` interface because `#add` and friends throw `UnsupportedOperationException`. In Scala, I would expect to find an appropriate trait with accessors like `iterator`, `size`, and `apply` (for retrieving values by index) but no mutators. Does such a type exist that I just haven't found yet?