30

The lack of reified generics in Scala is the thing that bugs me the most about the language, since simple things cannot be implemented without using complicated constructs.

Both Kotlin and Ceylon supports reified generics so its definitely possible to do so on top of the JVM. In the past it was said that Scala could not support them without a change in the JVM, but now Scala 2.10 is rumored to have limited support for reification. So my question is:

  • What can we expect for reification in Scala 2.10, will I for example be able to implement a generic trait multiple times ?. Just how limited is it ?
  • If Scala 2.10's reification turns out to be more limited than Kotlin and Ceylon. Why is that ?
Community
  • 1
  • 1
Lars Tackmann
  • 20,275
  • 13
  • 66
  • 83
  • I tried updating the question so it's now hopefully simpler to answer (as in Yes/No you cannot implement a generic trait multiple times in Scala 2.10 as the type reification will require name mangling in the generated classes, making them complicated to use in Java. Or whatever the answer might be. – Lars Tackmann Dec 22 '11 at 15:02
  • 4
    Odersky *said* reification is in 2.10, so it's more than a rumor. – Michael Lorton Dec 22 '11 at 16:48
  • 2
    You mean the non-existing Kotlin and the Ceylon-that-was-just-released-without-reification shows that reified generics is possible? How does that work? – Daniel C. Sobral Dec 22 '11 at 19:11
  • 13
    I cannot understand how this question can ever be considered "not constructive". The question is very objective and has clear answers, despite the reference to languages/features not yet available. – Daniel C. Sobral Dec 22 '11 at 21:02

3 Answers3

32

Your argument is flawed. Kotlin has not been released yet*, and Ceylon just had its first version released, and I'll quote one of the things it is missing from their announcement:

  • reified generics

So, excuse me, but what implementation proves it is possible? In fact, I haven't looked much at what Kotlin is promising, but what Ceylon is promising is just what manifests already provide, but in a transparent manner.

But let's consider the problem you described in your question:

trait Handles[E <: Event] {
  def handle(event: E)
}

So, first of all, JVM doesn't provide any way of identifying type parameters in interfaces or classes, so E cannot be checked by JVM. You can, however, store information about what E stands for in each object that implements Handles, just like you could write this in Scala:

abstract class Handles[E <: Event : Manifest] {
  def handle(event: E)
}

Next, let's see the method handle. Again, JVM provides no way of using type parameters in a method definition. The only way to implement that is to have handle accept Object as parameter: ie, type erasure.

And here's the deal: to make handle callable from Java, it must be type erased. And, if it is type erased, then it is subject to the limitation described in your question. The only way to get around that is to drop Java compatibility (which, by the way, is not available in Ceylon's first release either).

Yes, Scala will have reification (of some sort) on 2.10, according to Martin Odersky. But whatever it provides (and I'm betting on more transparent use of manifests to assert type equality), this particular limitation is intrinsic to JVM and cannot be overcome without dropping Java integration.

(*) Kotlin has a demo out now, and its reification -- so far -- is just a syntactic sugar for bundling manifests and instanceOf tests. It's still subject to all the same limitations Scala is.

Daniel C. Sobral
  • 295,120
  • 86
  • 501
  • 681
  • 1
    I assumed that since the specs mentioned reification (fx. http://goo.gl/jMvzG) that the authors have indeed found a way to do it. If not then you are of cause completely correct. My question was more on the nature of generics in 2.10 and why it is that kotlin and ceylon can solve this problem and Scala cannot (assuming they can). – Lars Tackmann Dec 22 '11 at 20:37
  • 4
    @Lars: No, there is no way to do proper reified generics on the JVM, without creating a completely new abstraction between the JVM, class-files, bytecode and the language. Despite the fact that two new languages claim to support reified generics, those languages have delivered nothing to this day except some prettified instanceOf tests. – soc Jan 12 '12 at 18:27
  • 1
    Gosu supports reified generics, and even though Kotlin and Ceylon don't have releases out that support them, there is no doubt in my mind they will as well. Having said that, I think adding reified generics in Scala is a mistake that will take a toll on the language, while needing access to generic information is pretty rare and usually met adequately with manifests. Gosu link: http://gosu-lang.org/doc/Gosu%20Reference%20Guide/wwhelp/wwhimpl/common/html/wwhelp.htm#context=gosu&file=intro.03.09.html – Cedric Beust Jan 13 '12 at 05:28
  • 4
    Although I know that no facts on this planet can change your one-and-true-opinion, did you even actually check your claims for a microsecond? :-) Just one example "Errors: A method with the same name reifies to the same signature at the bytecode level. Rename one of the methods.". Notice how conveniently "erases" got replaced by "reified"? I could go on if the compiler wouldn't be completely unstable and crash when trying to implement a simple interface ("java.lang.ClassFormatError: Illegal field modifiers in class program_/__Program__689"). – soc Jan 13 '12 at 07:09
  • And no, Kotlin basically does the same prettified instanceOf tests as Gosu and Ceylon delayed actual implementation. So I still would like to see an example of reified generics on the JVM. – soc Jan 13 '12 at 07:11
  • @Daniel you are right. It's still manifest (tied into the new scala reflection). See [Martin Odersky's answer on the mailing list](http://groups.google.com/group/scala-language/browse_thread/thread/31ce854f81fc518/56085fc38e239bed?lnk=gst&q=reified+2.10#56085fc38e239bed). – Paolo Falabella Jan 13 '12 at 11:14
  • Of course, the information has to be erased for Java interop, that's not what we're talking about. This kind of reification makes the information available at the source level, which is what Gosu, Kotlin and Ceylon do. And apparently, Scala soon, although I still think it's going to have more downsides than upsides. – Cedric Beust Jan 13 '12 at 18:48
  • Ceylon has fully reified generics now as of the M5 release. – Magnus Mar 30 '13 at 15:58
  • Ceylon link on this - http://ceylon-lang.org/blog/2013/02/21/reification-finally/ – Suminda Sirinath S. Dharmasena Nov 19 '13 at 16:32
  • @Daniel, your answer is outdated and should be updated to the current version of Kotlin, which is in its final betas. Kotlin has reified generics for inline functions only. – Jayson Minard Dec 29 '15 at 04:27
  • @JaysonMinard The question is also outdated. I've no interest in updating this -- you might have noticed that I didn't think the question was a good question in first place. Let others answer and get upvoted. – Daniel C. Sobral Jan 04 '16 at 19:42
  • 2
    A one-line update note at the top, would have been as fast as the comment you just left. – Jayson Minard Jan 04 '16 at 19:45
9

Kotlin has reified generics for inline function type parameters, as documented here: https://kotlinlang.org/docs/reference/inline-functions.html#reified-type-parameters. This has existed in Kotlin for some time now, they are used by many libraries already within the Kotlin ecosystem. Other answers here are out of date when referring to the Kotlin. Kotlin has been released as 1.0 since February, 2016.

Examples of reified generics in Kotlin, the famous TypeReference in Jackson, when used in the Jackson Kotlin module uses this code:

public inline fun <reified T: Any> ObjectMapper.readValue(jp: JsonParser): T 
     = readValue(jp, object: TypeReference<T>() {})

And the same thing from the Kotlin based Injekt library:

public inline fun <reified T: Any> fullType(): FullTypeReference<T> 
    = object:FullTypeReference<T>(){}

public inline fun <reified T : Any> injectLazy(): Lazy<T> {
    return lazy { Injekt.get(fullType<T>()) }
}
Jayson Minard
  • 84,842
  • 38
  • 184
  • 227
2

According to what Andrey Breslav is saying on this page Kotlin does not have reified types:

"Yes, type parameters are not available in class objects"

brasofilo
  • 25,496
  • 15
  • 91
  • 179
OlliP
  • 1,545
  • 11
  • 22
  • 3
    Reified types are dropped in Kotlin: "Reified generics can be implemented for JVM only with big performance overhead, and we decided to cancel this feature.". See http://devnet.jetbrains.com/message/5479326#5479326 – OlliP Feb 19 '13 at 16:37
  • 2
    Meanwhile, the next milestone release of Ceylon will include reified generics http://www.ceylon-lang.org/blog/2013/02/21/reification-finally/ – Chochos Feb 21 '13 at 18:30
  • 3
    @Ollip your answer should be updated, Kotlin does have reified generics for inline functions which are used heavily and solve most common cases. Your answer is now misleading for current Kotlin. – Jayson Minard Dec 29 '15 at 04:27