3 ms·
Type erasure gets blamed for too much. Want to see some languages that make generics sing? Take a look at SML, Haskell, or Rust. What's another interesting char
by mumblemumble 5y ago
Type erasure gets blamed for too much. Want to see some languages that make generics sing? Take a look at SML, Haskell, or Rust. What's another interesting characteristic that unites them? They erase all types. Not just generic type parameters like Java does. Everything is type erased. And they do just fine.
I would argue that the real problem with Java's rollout of generics is at the language level. The language itself introduced some strange gaps in the semantics of generics, such as failing to build any decent bridges between arrays and generic collections. I don't know that this was necessary. Scala and Kotlin are working out OK, and they have unified arrays with generics. And the other problem is that generic types are not exactly first-class types in Java, even before type erasure takes place. This means handling some key use cases for generics requires resorting to the "super type token" pattern, which is awkward and still not all that well known.
I don't think I'm alone in this sentiment. Coders at Work has an interview with a developer who worked on Java 5, and he also expresses a belief that, in retrospect, the problem with Java generics wasn't type erasure, it's that they rushed the feature and some of the language-level design characteristics weren't fully baked yet. (He didn't go much into specifics, though, so I can't say if our opinions agree in the specifics.)
- messe 5y agoI was under the impression that Rust uses monomorphization, not type erasure in its implementation of generics? (Although it does have a form of type-erasure in &dyn Trait objects)
- mumblemumble 5y agoIt monomorphizes generic functions and methods. Type erasure happens to the actual values. So, for example, at run time an Option<i32> ends up just storing one word for indicating whether it's Some or None, and another for the value when it's Some, but doesn't store any information to indicate that those 8 bytes represent an Option<T> of any kind, let alone exactly what kind of value is being stored in it. None of that is needed at run time, because the compiler was able to statically verify that no function is going to try to read them as a u64 instead.
- jcelerier 5y agoI have never heard such a definition of type erasure, generally it means that the concrete type is hidden behind a generic "OO" interface which is itself hidden behind a value type providing the same interface / API
- ragnese 5y ago> Type erasure gets blamed for too much. Want to see some languages that make generics sing? Take a look at SML, Haskell, or Rust. What's another interesting characteristic that unites them? They erase all types. Not just generic type parameters like Java does. Everything is type erased. And they do just fine. You're both right and wrong. You're technically correct, which we all know is the best kind of correct, but you're wrong because you're leaving out very important Gestalt context. (EDIT: Actually, you vaguely touch on it, but you focus on arrays and Lists, which I think misses the point) You're correct because Rust and Haskell, et al, have fully erased types (well... Rust has trait objects, which are implemented with vtables- does that count?), and nobody really complains about it. So, in a very specifically-literal sense, you're right that it's not the type-erasure that is the (sole) problem in Java. The real problem is that Java is BIG on *runtime reflection*. You can't "reflect" on types that don't exist, so every time you do use reflection (which is approximately 100% of Java projects) and generics (which is also approximately 100% of Java projects), you're in for nonsense. Between generics, reflection, and null, I literally feel my blood pressure rise when I think about dealing with Java, and even Kotlin. Where Java leans on runtime reflection, Haskell and Rust cannot and do not. And, therefore, the communities have found compile-time (or just tedious write-time) solutions to things like (de)serialization. So, type erasure isn't the problem, and runtime reflection isn't a problem. But you can't do both and expect anything good to come of it.
- deleted 5y ago[deleted]
- ragnese 5y ago> I would argue that the real problem with Java's rollout of generics is at the language level. The language itself introduced some strange gaps in the semantics of generics, such as failing to build any decent bridges between arrays and generic collections. I don't know that this was necessary. It was necessary. Java made the mistake of letting primitive arrays be (incorrectly) covariant in their type param. Java's implementation of generics is, fortunately, correct in how it handles type parameter variance. However, this means that they are incompatible with Java's primitive arrays. I don't think there is a way to "bridge" them seamlessly without making generics unsound.
- shlurpy 5y agoThe difference is subtypes being treated as super types, ie, OOP stuff. Type erasure is different in a language where basically any typed value could also contain a value of any subtype. All those other languages you mention make that functionality opt in, which is why they aren't object oriented languages.
- mumblemumble 5y agoOne could imagine, though, an object-oriented language that doesn't retain objects' actual types, just pointers to their virtual function tables. Perhaps, as an optimization, it even skips that in cases where it can prove that all method calls can be statically dispatched.