Search code examples
scalacollectionslong-integervalue-typeautoboxing

Do AnyVal elements inside specialized collections need boxing?


Say I have a custom class which extends AnyVal and uses a Long internally:

case class Instruction(underlying: Long) extends AnyVal

When I add Instructions to a collection which is specialized for Long, do the Instructions need boxing?

(Are there Scala collections which are specialized for Long? I need an indexed sequence.)


Solution

  • Yes, it will be boxed. Unfortunately, value classes lose all their benefits when used as type arguments (generics) or put into collections. They are boxed always when they need to be seen as any other type than exactly the type of the value class itself.

    The reason for that limitation is that to retain sound semantics of Scala language, code like this must work:

    case class ValueClass(raw: Long) extends AnyVal
    val someList: List[Any] = List[ValueClass](ValueClass(42L))
    someList.head match {
      case ValueClass(raw) => // boxing needed for this match to work...
      case _ => ...
    }
    

    Specialization doesn't change anything here, any collection (specialized or not) could be passed somewhere where it's seen as Coll[Any] or Coll[T] where information about exact element type is lost.

    If you want an IndexedSeq[Long] with unboxed storage, I think scala.collection.mutable.WrappedArray.ofLong is the closest thing to that. It also has its corresponding builder, scala.collection.mutable.ArrayBuilder.ofLong.