Chris Martin Chris Martin - 8 months ago 34
Scala Question

Unmodifiable view of a mutable Scala collection

I have a class with a private field that is a mutable collection. The field in this particular instance is an

, 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
that doesn't fully implement the
interface because
and friends throw

In Scala, I would expect to find an appropriate trait with accessors like
, and
(for retrieving values by index) but no mutators. Does such a type exist that I just haven't found yet?


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


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


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.