def evenElems[T](xs: Vector[T])
(implicit m: ClassManifest[T]): Array[T] = ...
Using an alternative and shorter syntax, you can also demand that the type comes with a class manifest by using a context bound. This means following the type with a colon and the class name ClassManifest, like this:
// This works
def evenElems[T: ClassManifest](xs: Vector[T]): Array[T] = { val arr = new Array[T]((xs.length + 1) / 2)
for (i <- 0 until xs.length by 2) arr(i / 2) = xs(i)
arr
}
The two revised versions of evenElems mean exactly the same. What happens in either case is that when the Array[T] is constructed, the compiler will look for a class manifest for the type parameter T, that is, it will look for an implicit value of type ClassManifest[T]. If such a value is found, the manifest is used to construct the right kind of array. Otherwise, you’ll see an error message like the one shown previously.
Here is an interpreter interaction that uses the evenElems method:
scala> evenElems(Vector(1, 2, 3, 4, 5)) res6: Array[Int] = Array(1, 3, 5)
scala> evenElems(Vector("this", "is", "a", "test", "run")) res7: Array[java.lang.String] = Array(this, a, run)
In both cases, the Scala compiler automatically constructed a class manifest for the element type (first Int, then String) and passed it to the implicit parameter of the evenElems method. The compiler can do that for all concrete types, but not if the argument is itself another type parameter without its class manifest. For instance, the following fails:
scala> def wrap[U](xs: Vector[U]) = evenElems(xs) <console>:6: error: could not find implicit value for
evidence parameter of type ClassManifest[U] def wrap[U](xs: Vector[U]) = evenElems(xs)
ˆ