11 ms·
LOL, record was an intentional omission during designing Java, similar to output parameters in function calls. It's not like James didn't know about them or cou
by bitL 7y ago
LOL, record was an intentional omission during designing Java, similar to output parameters in function calls. It's not like James didn't know about them or couldn't implement them.
The only truly problematic thing in the original Java design was type erasure, leading to mess in all JVM-based languages like Scala, Kotlin or Clojure, but it saved some memory, so it was a design compromise. C#/CLR chose the other option, making their VM more flexible.
- pron 7y agoType erasure of generic parameters is what allows the Java language, Kotlin, Clojure, JavaScript and other Java platform languages to interoperate so well and share data types with no runtime conversions despite having different variance strategies. By baking variance into the VM, .NET is much less flexible, as can be seen by how cumbersome it is to share data structures among different languages.
- dwohnitmok 7y agoHow is that? I don't have as much experience with .NET languages so I'm not sure of what difficulties lie in .NET interop, but from my very cursory experience with F# And C# I didn't find anything particularly difficult about using one's data structures in the other (granted they don't have different variance strategies). What about Java's type erasure lets languages play better with variance strategies and data structures? It's not apparent to me that e.g. IronPython has a hard time sharing data structures with C# (although I haven't actually used IronPython FWIW). Why doesn't the usual strategy of upcast everything to `Collection<Object>` within a language where collections are covariant and then downcast as needed in a language that doesn't care about variance (e.g. a dynamic language) work?
- pron 7y ago> granted they don't have different variance strategies ... because it's baked into the platform. > It's not apparent to me that e.g. IronPython has a hard time sharing data structures with C# https://ironpython.net/documentation/dotnet/dotnet.html#accessing-generic-types https://ironpython.net/documentation/dotnet/dotnet.html#acce... > Why doesn't the usual strategy of upcast everything to `Collection<Object>` within a language where collections are covariant and then downcast as needed in a language that doesn't care about variance (e.g. a dynamic language) work? Because that does not work for mutable collections, or even for immutable collections created by, say, an untyped language. Clojure can create a list of strings and pass it to a Java method expecting a List<String>.
- dwohnitmok 7y agoRight but my impression was that that was basically a performance optimization for IronPython, similar to type hints for Clojure and that they aren't actually necessary. IronPython was mainly what I was thinking when it comes to alternate variance strategies. I mean most typed languages I know of with stricter typing regimes than Java either all have the same variance schemes or eschew subtyping altogether, JVM, CLR, or otherwise. Why doesn't that work for mutable collections (are you referring to the need to be invariant here?) or immutable collections? More specifically, why can't you always have `Collection<A>`, upcast to `Collection<Object>`, downcast to `Collection<B>` as an escape hatch? You break type safety but erased generics already break type safety (this is especially clear with C#'s choice to follow Java's convention on array variance and the pain that this causes when it's inconsistent with everything else in C#). For passing back to a typed language, you add a downcast of `Collection<Object>` to `Collection<String>` and have no runtime conversion cost. Why doesn't that work? EDIT: Ah I see, is the basic problem you don't get free (more accurately cheap) casts, especially with generics? I'm not familiar with how casting works in the CLR since the vast majority of my time is on the JVM.
- pron 7y ago> are you referring to the need to be invariant here Yes, or contravariant. > erased generics already break type safety They don't, they just don't enforce type safety across languages. BTW, most languages erase types (including Haskell). > Why doesn't that work? Because platforms with safe casts do a runtime instanceof test, and if the platform reifies generics, then it is not true that the runtime type of Collection<Object> can be cast to Collection<String>. But if the generic parameter is erased, they both have the same runtime type.
- dwohnitmok 7y agoSure, Haskell relies on parametric polymorphism and typeclasses to get away with full type erasure with opt-in reification via Typeable. C++ does something similar with templates and has opt-in reification with RTTI. The JVM is just weird because it has some type reification, but not all the way. RE type safety, it doesn't really make sense to talk about type safety across languages since type safety is tied to a particular language's semantics. I would argue that every ClassCastException is a violation of type safety in Java the language even if it's reasonable at the JVM level but whatever that's just definitions diving. I see. Basically what you're saying is that you don't really see examples of reified types with unsafe runtime casts? Presumably because that kind of negates the whole point of reifying the types in the first place?
- paulddraper 7y ago> leading to mess in all JVM-based languages like Scala, Kotlin or Clojure !!! Type-erasure of generics is what gives the other languages flexibility. Scala eventually gave up C# precisely because CLR reification proved a huge challenge with Scala semantics. You may not like JVM type-erasure but Scala would literally not be possible without it. --- If anything, I would argue that Java should have done full type-erasure, not just type-erasure of generic types. (That does come with downsides though.)
- bitL 7y ago> Scala eventually gave up C# precisely because CLR reification proved a huge challenge with Scala semantics. In other words, Scala was designed on a hack involving JVM's type erasure, then authors found out the hack can't be ported to CLR. That's another way to view it. Type erasure is a half-baked mess in original Java, it was causing headaches right with the first version of generics...
- pron 7y agoType erasure is not a hack. It's the most common technique in typed languages. It causes what is, at worst, a minor inconvenience in the Java language in exchange for making the Java platform a very attractive and very convenient target for languages. Reification -- and I believe .NET is the only platform with variance that does it -- makes a very inconvenient compilation target for any language not designed around it.
- bitL 7y agoThat sounds as ex post facto justification. IIRC the designers hit the issue once they started implementing generics and the gravity of the situation became apparent just at that time. Then another set of hackers figured out a way to utilize it for language interoperability. I am not saying CLR's final implementation is great either, but it addresses some points JVM missed as they had time to learn from SUN's mistakes, while making their own errors in the process as well. Language/platform design is notoriously difficult and unpredictable.