views:

564

answers:

3

I've recently started learning Scala and was disappointed (but not surprised) that their generics are also implemented via type erasure.

My question is, is it possible for Scala to have reified generics, or would the JVM need to be changed in some way? If the JVM does need to be changed, what exactly would need to be changed?

+15  A: 

No - it is not possible for Scala to run as Java-equivalent bytecode if that bytecode does not support reified generics.

When you ask "what is it that needs to be changed?", the answer is: the bytecode specification. Currently the bytecode does not allow for the parametrized type of a variable to be defined. It has been decided that as a modification to the bytecode to support reified generics would break backwards compatibility, that generics would have to be implemented via type erasure.

In order to get around this, Scala has used the power of its implicit mechanism to define a Manifest which can be imported in any scope to discover type information at runtime. Manifests are experimental and largely undocumented but they are coming as part of the library in 2.8. Here is another good resource on Scala reified generics / Manifests

oxbow_lakes
Any links where I can read up on this?
cdmckay
Links being added as you speak :-)
oxbow_lakes
I had no idea the Scala guys were doing this. This is very cool.
cdmckay
Small correction: Manifests have been an experimental part of the standard library since 2.7.2. I don't know whether they will be any less experimental in 2.8.
Jorge Ortiz
Thanks *Jorge*. I was going from the current 2.8 scaladoc which includes manifests.
oxbow_lakes
+3  A: 

Just to complement oxbow_lakes, there's a question on Stack Overflow about how to get around type erasure in Scala.

Daniel
+1  A: 

"implicit Manifest" is a Scala compiler trick and it does not make generics in Scala reified. The Scala compiler, when it sees a function with "implicit m: Manifest[A]" parameter and it knows the generic type of A at the call site, it will wrap the class of A and its generic type parameters into a Manifest and make it available inside the function. However, if it could not figure out the true type of A, then it has no way of creating a Manifest. In other words, Manifest has to be passed along the function calling chain if the inner function needs it.

scala> def typeName[A](a: A)(implicit m: reflect.Manifest[A]) = m.toString
typeName: [A](a: A)(implicit m: scala.reflect.Manifest[A])java.lang.String

scala> typeName(List(1))
res6: java.lang.String = scala.collection.immutable.List[int]

scala> def foo[A](a: A) = typeName(a)
<console>:5: error: could not find implicit value for parameter m:scala.reflect.Manifest[A].
       def foo[A](a: A) = typeName(a)
                                  ^

scala> def foo[A](a: A)(implicit m: reflect.Manifest[A]) = typeName(a)
foo: [A](a: A)(implicit m: scala.reflect.Manifest[A])java.lang.String

scala> foo(Set("hello"))
res8: java.lang.String = scala.collection.immutable.Set[java.lang.String]
Walter Chang
Why don't they just invisibly add a Manifest to every method call that has generics? Do Manifests incur a performance penalty?
cdmckay
I'm not sure that anyone here has said that manifests make generics reified (which seems to be your implication). I said that Manifests can be imported to derive type information at runtime whereas reified generics would require a change to the bytecode specification.
oxbow_lakes
@oxbow_lakes I am sorry if my answer came across like that; I didn't mean to imply anyone said anything about "manifests make generics reified". All I wanted to point out is some limitations on using Manifest.
Walter Chang