Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best practice: "If not immutable create copy"-pattern

I have function which gets a Seq[_] as an argument and returns an immutable class instance with this Seq as a val member. If the Seq is mutable I obviously want to create a defensive copy to guarantee that my return class instance cannot be modified.

What are the best practice for this pattern? First I was surprised that it is not possible to overload the function

  def fnc(arg: immutable.Seq[_]) = ...
  def fnc(arg: mutable.Seq[_]) = ...

I could also pattern-match:

  def fnc(arg: Seq[_]) = arg match {
    case s: immutable.Seq[_] => { println("immutable"); s}
    case s: mutable.Seq[_] => {println("mutable"); List()++s }
    case _: ?
  }   

But I am not sure about the _ case. Is it guaranteed that arg is immutable.Seq or mutable.Seq? I also don't know if List()++s is the correct way to convert it. I saw many posts on SO, but most of them where for 2.8 or earlier.

Are the Scala-Collections "intelligent" enough that I can just always (without pattern matching) write List()++s and I get the same instance if immutable and a deep copy if mutable?

What is the recommend way to do this?

like image 901
Manuel Schmidt Avatar asked Jun 16 '26 14:06

Manuel Schmidt


1 Answers

You will need to pattern match if you want to support both,. The code for Seq() ++ does not guarantee (as part of its API) that it won't copy the rest if it's immutable:

scala> val v = Vector(1,2,3)
v: scala.collection.immutable.Vector[Int] = Vector(1, 2, 3)

scala> Seq() ++ v
res1: Seq[Int] = List(1, 2, 3)

It may pattern-match itself for some special cases, but you know the cases you want. So:

def fnc[A](arg: Seq[A]): Seq[A] = arg match {
  case s: collection.immutable.Seq[_] => arg
  case _ => Seq[A]() ++ arg
}

You needn't worry about the _; this just says you don't care exactly what the type argument is (not that you could check anyway), and if you write it this way, you don't: pass through if immutable, otherwise copy.

like image 71
Rex Kerr Avatar answered Jun 18 '26 02:06

Rex Kerr