6 ms·
What a fascinating design constraint: to retrofit a useful feature into the Java ecosystem while keeping as many things backwards-compatible as possible. This p
by niftich 8y ago
What a fascinating design constraint: to retrofit a useful feature into the Java ecosystem while keeping as many things backwards-compatible as possible. This proposal has a much stronger answer to backward compatibility than the previous one, by letting all ported builtin classes keep the same descriptor in the bytecode. The catch is that each class file will now declare which of the types it imports are ValueTypes, and which aren't.
Java's strong commitment to bytecode-level backwards-compability is sometimes to the detriment of its feature-set (e.g. non-reifiable generic types due to type erasure), but this commitment is a large contributor to the platform's success.
- kjeetgill 8y agoFor what it's worth, Brian Goetz doesn't see type-erasure as a such a failure and defends the design choice[0]. [0]:https://m.youtube.com/watch?v=TkpcuL1t1lY https://m.youtube.com/watch?v=TkpcuL1t1lY
- noelwelsh 8y agoI'd say the mainstream programming language theory view is that type erasure is the correct approach. See https://en.wikipedia.org/wiki/Parametricity https://en.wikipedia.org/wiki/Parametricity
- eecc 8y agoPardon my ignorance but I don’t see how the Wikipedia link supports your statement. Can you please elaborate?
- noelwelsh 8y ago"parametrically polymorphic" == has a generic type. So a function foo[A](x: A) = ??? // Implementation hidden for now is parametrically polymorphic, where A is the generic type (or type variable). The principle of parametricity says that `foo` should act in the same way no matter what type of value it is called with. Type erasure ensures this, because it prevents `foo` from inspecting the (reified) type at runtime. If types are not erased then `foo` can behave differently when given, say, a `String` or an `Int`. Why is parametricity important? It makes code easier to reason about. Parametricity means no special cases to remember. It makes everything more uniform and simpler. In fact there is only one valid implementation of `foo` above, and this is the identity function. foo[A](x: A) = x Looking just at the type signature of `foo` tells you everything there is to know about it---which is quite remarkable! This reasoning principle is sometimes called "free theorems".
- amaranth 8y agoThis is an argument against specialization, not against reification. With type erasure your compiler can't perform type-specific optimizations, at least not without a JIT and borrowing some optimization techniques from dynamically typed languages.
- noelwelsh 8y agoI don't think we agree on definitions of terms here. For me type erasure means that the programmer cannot access a runtime representation of a type. A "runtime representation" is what I mean by "reified", as from the programming language theory perspective types only exist at compile time (and it is values that exist at runtime). Type erasure, as I use the term, is compatible with type specific optimisation. For example, the MLton compiler for Standard ML supports monomorphisation of polymorphic code, which in turn allows unboxing: http://mlton.org/Monomorphise http://mlton.org/Monomorphise The compiler is free to use whatever representation it likes, which includes a reified representation for use in, say, dynamic linking, so long as it doesn't break the language semantics (by exposing this to the programmer, for instance).
- amaranth 8y agoOf course, guess I shouldn't comment before the caffeine kicks in... I was thinking without reified types the JIT can't optimize it easily then got stuck on that. Of course the compiler could do so, Java just doesn't have an optimizing compiler.
- pron 8y agoI believe that the class file does retain the specific generic instance at the use-site, it's just that there isn't much type-specific optimization that's applicable to reference types beyond what HotSpot does anyway (which is stronger than what would be available by the generic instance type information). It's possible that Java AOT compilers could make use of this information.
- DougBTX 8y ago
- tome 8y agoThe argument goes something like "Parametricity is a good thing and you can't have parametricity without erasure".
- pron 8y agoJust a nitpick: programming language theory makes absolutely no judgment on what is a correct or incorrect approach [1]. It just studies the implications of various language designs. In this case it says something close to, if you have erasure then you have parametricity, and it also says what parametricity guarantees. It does not and cannot, however, claim that this is the "correct" way. In general, mathematical theories do not have an intrinsic notion of empirical value. [1]: Although some PL theorists may, but this is an expression of their opinion, not something that comes out of the theory.
- pron 8y agoNon-reified generics is the feature that allows different JVM languages to interoperate much more easily and share data structures. If you look at the CLR, interop there is much messier, largely due to this. The reason is that if reference-type generics were reified, then the JVM must know the subtyping relationship between such different types, and different languages have very different variance strategies. This limitation does not apply to types that cannot be subtyped, which is why value type generics can (and will) be reified. In exchange, you pay with a minor nuisance: mostly the inability to overload methods with the same erased types. I think most would agree that having a truly polyglot VM that allows different languages to enjoy the data structures written in other languages is much more important.
- bradleyjg 8y agoIt’s an interesting trade-off. It makes java a somewhat weaker language but the jvm a better platform. At the time the decision was made, probably no one was thinking of the jvm as polyglot platform. So there was a decision whose chief benefit was only revealed in retrospect.
- bunderbunder 8y agoIt's also possibly an unnecessary trade-off. Scala, for example, has something akin to reified generics, without any support from the JVM itself. It also allows for a decent level of interop with other JVM languages, though of course all you can really "export" to other languages is the least common denominator semantics required by the JVM. Java could theoretically do something similar: Maintain type information that is visible to Java at compile- and run-time, while still compiling to code that is consumable from other languages without too much hassle. Really, personally, I only care about it being available at compile time. Haskell, for example, erases types much more aggressively than Java does, while also maintaining a high level of type safety. I guess I don't know that it's backwards compatibility on the JVM that bothers me so much as Java's tendency to think of itself as being little more than a JVM macro assembler with C-like syntax.
- 8y ago