Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 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?

like image 988
Chris Martin Avatar asked Nov 21 '12 06:11

Chris Martin


People also ask

What are the mutable collections in Scala?

Scala collections systematically distinguish between mutable and immutable collections. A mutable collection can be updated or extended in place. This means you can change, add, or remove elements of a collection as a side effect. Immutable collections, by contrast, never change.

Is list mutable or immutable in Scala?

Lists are immutable whereas arrays are mutable in Scala.

How can we convert mutable map to immutable Scala?

If you just want a mutable HashMap , you can just use x. toMap in 2.8 or collection. immutable. Map(x.

What does ++ mean in Scala?

++= can mean two different things in Scala: 1: Invoke the ++= method. In your example with flatMap , the ++= method of Builder takes another collection and adds its elements into the builder. Many of the other mutable collections in the Scala collections library define a similiar ++= method.


1 Answers

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.

like image 137
Marius Danila Avatar answered Sep 18 '22 11:09

Marius Danila