You can do this using scala.collection.immutable.Map with a little implicit magic. That is, you define one additional method in the interface and an implicit conversion. Here, as I will do this in version 2.7, I am sure that in 2.8 there are several ways to override, but you should get a general idea.
trait Unoverwriteable[A, B] extends scala.collection.immutable.Map[A, B] { import Unoverwriteable.unoverwriteableMap case class KeyAlreadyExistsException(e: String) extends Exception(e) def underlying: scala.collection.immutable.Map[A, B] def update [B1 >: B] (key: A, value: B1): Unoverwriteable[A, B1] = { if (this contains(key)) throw new KeyAlreadyExistsException( "key already exists in WritableOnce map: %s".format(key.toString) ) underlying update (key, value) } def get(key: A): Option[B] = underlying get key def elements: Iterator[(A, B)] = underlying.elements def -(key: A): Unoverwriteable[A,B] = underlying - key def empty[C]: Unoverwriteable[A,C] = underlying.empty[C] def size: Int = underlying.size }
Then you define the implicit in the companion object:
object Unoverwriteable { implicit def unoverwriteableMap[A, B](map0: scala.collection.immutable.Map[A, B]): Unoverwriteable[A, B] = new Unoverwriteable[A, B] { def underlying = map0 } }
To use it, add an Unwriteable type annotation to your map. If you uncomment the last 2 lines in the main method, you will get a KeyAlreadyExistsException.
object UOMain { def main(args: Array[String]): Unit = { val map0 = Map((1 -> 1), (2 -> 2)): Unoverwriteable[Int, Int] println("map0="+ map0) val map1 = map0 - 2 println("map1="+ map1)
Garrett rowe
source share