How can I get an empty collection of the same type as a given instance?

As part of a rewriting mechanism, I need to obtain and execute a collection constructor of the same type as a given instance. The code below summarizes my attempt.

import scala.reflect.runtime.universe.TypeTag
def getEmptyCollection[N : TypeTag](collection: N): N = {
  val runtime = scala.reflect.runtime.universe
  val mirror = runtime.runtimeMirror(getClass.getClassLoader)
  val classSymbol = runtime.typeOf[N].typeSymbol.asClass
  val classMirror = mirror.reflectClass(classSymbol)
  val constructorSymbol = runtime.typeOf[N].decl(runtime.termNames.CONSTRUCTOR).asMethod
  val constructorMirror = classMirror.reflectConstructor(constructorSymbol)
  constructorMirror()
}

val emptyList: List[Int] = getEmptyCollection(List(1, 2, 3))

This code, though, produces an instantiation exception: java.lang.InstantiationException was thrown

Perhaps "typeOf[N]" is the problem, but I'm just guessing. Would you know what the problem might be?

Thank you!

Upvotes: 2

Views: 191

Answers (1)

Alexey Romanov
Alexey Romanov

Reputation: 170919

The correct way (in Scala 2.12, probably somewhat different in 2.13 while 2.11 will need explicit type parameters):

import scala.collection.generic.GenericTraversableTemplate
import scala.collection.GenTraversable

def getEmptyCollection[A, CC[X] <: GenericTraversableTemplate[X, CC] with GenTraversable[X]](collection: CC[A]) = 
  collection.genericBuilder[A].result()

println(getEmptyCollection(List(1, 2))) // List()
println(getEmptyCollection(Vector(1, 2))) // Vector()

No reflection required!

Upvotes: 6

Related Questions