7 ms·
> First off, I've seen some people suggest that type erasure is a problem because it leads to a loss of type safety. This isn't really true. I'd argue it's the
by hota_mazi 8y ago
> First off, I've seen some people suggest that type erasure is a problem because it leads to a loss of type safety. This isn't really true.
I'd argue it's the opposite.
Giving your programs the ability to access reified types at runtime weaken the robustness of your code, because you can second guess the compiler and introduce crashing code, such as incorrect type casts.
Reification also comes at a cost: performance, more problematic interoperability (Scala could notoriously not be ported to .net because it was not possible to make its type system work properly on a reified platform).
Contrary to popular belief, Java's choice of erasure was not dictated by backward compatibility concerns but because erasure is a sound approach for type system representation.
- seanmcdirmid 8y agoScala could be ported .net easily enough, but it couldn’t interop with reified generic APIs. MS actually doesn’t use generics as aggressively as it could in its API for similar reasons (eg there are two APIs for collections that use genetics and don’t).
- bunderbunder 8y agoMy understanding is that the problem was, more specifically, that they couldn't easily get Scala's types mated to .NET, and that was in turn an implication of the decision to use IKVM to run the Java binaries for Scala's standard libraries on the CLR. Which I could see being a problem, because then you need to figure out how to smoothly marshal data back and forth between (type erased) Scala collections and .NET functions, which typically expect reified types these days. If they had gone with producing a .NET native version of Scala's standard libraries, they might have had easier success. But it also would have been a Pyrrhic victory, because you'd have lost the ability to run any existing Scala code, which would have scads of dependencies on other bits of the JDK as well, on Scala for .NET. At which point, what's the point? I expect that porting F# to the JVM would encounter similar problems. And I expect that which platform you want to blame them on depends on which one is your home platform. IMO the real story here is that the two big managed platforms are effectively walled gardens, by virtue of having VMs that implement such very high-level bytecode. Both of them effectively demand that all languages running on them can interact with, in effect, a thoroughly object-oriented ABI. There being approximately as may flavors of OOP as there are OO languages, that creates a situation where, if your language isn't set up to play nice with that platform's particular brand of OOP, you're going to have a bad time.
- dtech 8y ago> But it also would have been a Pyrrhic victory, because you'd have lost the ability to run any existing Scala code, which would have scads of dependencies on other bits of the JDK as well, on Scala for .NET. At which point, what's the point? Ask the parade of JVM languages porting themselves to native and JS runtimes.
- bunderbunder 8y agoThose are both very different use cases.
- tutanchamun 8y agoWhy are they very different? They port the language over to another platform and need to interop with it. For example scala.js can call js libraries through facades (similar to typescript typing files) but can also be called from javascript. Scala.native can call c libraries (I have no idea about the other way around).
- bunderbunder 8y agoTargeting native because it's fundamentally a less thorny issue. To an approximation, all you do is take the JIT compilation pipeline and use it to do an AOT compilation instead. Targeting JavaScript because people expect different things out of it. The goal there is to transpile some portion of your code to run on the browser. There's not the same expectation that you'll be able to truck Spring or Akka along with you. The expectation is that the transpiled code is mostly only going to interact with the DOM and other JavaScript libraries, plus maybe whatever subset of your business objects you feel the need to have on both the client and server side. By contrast, the only real use case I can see for porting Scala to .NET is so that you can bring a bunch of pre-existing Scala libraries with you and then interface them with some pre-existing .NET codebase. If you're not looking for that, you'd probably be willing to satisfy yourself with either F# or the JVM.
- seanmcdirmid 8y ago
- benaadams 8y ago> MS actually doesn’t use generics as aggressively as it could in its API for similar reasons (eg there are two APIs for collections that use genetics and don’t). Object based collections are generally deprecated over the generic versions and were existed prior to generics being introduced.
- seanmcdirmid 8y agoYou’ll see that they still get a lot of use in the interfaces of non deprecated APIs (eg WPF).
- merb 8y agoto be fair, they tried to kill of winforms and wpf. I mean they invented uwp and I doubt that they did not wanted to maintain three of these gui frameworks.
- seanmcdirmid 8y agoAgreed. But I don't think UWP uses generics very much (if at all) either. To be honest, it feels like Microsoft's UI strategy these days is either UWP for the store or just use the web.
- benaadams 8y agoCan use the Desktop Bridge https://docs.microsoft.com/en-us/windows/uwp/porting/desktop-to-uwp-root https://docs.microsoft.com/en-us/windows/uwp/porting/desktop... with .NET Core 3.0 and the newly open sourced UI frameworks to get full Jitting and Store access (UWP is microsoft-ui-xaml https://github.com/Microsoft/microsoft-ui-xaml https://github.com/Microsoft/microsoft-ui-xaml)
- merb 8y agoit's ot, but still... > Microsoft's UI strategy at the moment I really think that they do not have a strategy. I mean they even have Xamarin.Forms which is another XAML variant. which ups their UI stuff to 4. I do not see any of them being deprecated at all.
- int_19h 8y ago> MS actually doesn’t use generics as aggressively as it could in its API for similar reasons (eg there are two APIs for collections that use genetics and don’t). All modern .NET APIs use generics heavily, and have done so since at least C# 3.5 (e.g. LINQ is pretty much all generics). The reason why there are two collection APIs is because one of them predates generics. It is generally considered deprecated and rarely used, with exception of untyped IEnumerable, and that mostly because it's the base interface of IEnumerable<T>. It's not dissimilar to how Java also has legacy collections from 1.0 days.
- CuriousSkeptic 8y agoThe non-generic super-interface pattern isn’t completely deprecated. It’s still advocated as a workaround for the lack of existential types in the language.
- dllthomas 8y ago> Contrary to popular belief, Java's choice of erasure was not dictated by backward compatibility concerns but because erasure is a sound approach for type system representation. Do you have evidence for the "because"? I agree that erasure is a sound approach for type system representation when designing a language, but I thought that backwards compatibility was explicitly a concern in the case of Java. Also, that good languages can be built with type erasure doesn't mean it's a good fit for the Java context where the runtime is doing a lot of dynamic dispatch based on tags that now only represent a part of the type.
- hota_mazi 8y ago> Do you have evidence for the "because"? I agree that erasure is a sound approach for type system representation when designing a language, but I thought that backwards compatibility was explicitly a concern in the case of Java. When the debate was raging around 2004 when generics were being discussed, Neal Gafter offered a proposal of a reified JVM that would maintain backward compatibility. Erasure was ultimately chosen over that proposal. Backward compatibility was not the issue: technical soundness was.
- dtech 8y ago> Contrary to popular belief, Java's choice of erasure was not dictated by backward compatibility concerns but because erasure is a sound approach for type system representation. This is false. I cannot find the source at the moment, but in a talk about implementing improved lambda support in Java 8 a Java compiler dev clearly labeled type erasure as technical debt they have to work around. It frequently bites them when they try to implement new things, and causes weird interaction with new language features they have to work around.
- merb 8y agowell to be fair, with this debt they came up with something really useful. indy and lambdametafactory
- jayd16 8y agoIn other talks Java language devs mention it as a conscious design choice.
- Someone 8y agoReading JSR-14 (https://download.oracle.com/otndocs/jcp/7566-generics-0.1-prd-spec-oth-JSpec/ https://download.oracle.com/otndocs/jcp/7566-generics-0.1-pr...), it was a conscious choice: ”Supporting generic types at run time seems undesirable for the following reasons: - Lack of experience with such constructs in widely used languages - Burden of extensive VM changes on vendors throughout the industry - Increased footprint on small devices - Decreased performance for generic methods - Compatibility” However, that doesn’t rule out it is technical debt, too. “Conscious design choice” and “technical debt” do not rule out each other.
- slavapestov 8y ago> Reification also comes at a cost: performance On the contrary, reified generics give the implementation more leeway with representation choices which can help with performance. In Java for instance a `List<Integer>` is stored as an array of boxed Integer objects, without easily being able to store the values inline.
- bunderbunder 8y agoThat can be done even more easily with properly erased generics. This is another of those unfortunate implications of Java's having disappeared into this ugly chasm between static and dynamic typing. It doesn't fully erase types, so you can't do like C++ or Haskell do and just generate a completely different type, because it wouldn't be compatible with any functions that work with the generic type. At least, not without breaking backward compatibility, which was the whole point of doing type erased generics in the first place.
- dtech 8y agoI'm curious, what is not "proper" about Java's erased generics? Reified types also bring other advantages, e.g. runtime reflection can be useful and can enable meta-programming and allows check binary compatibility of dynamic linking. So gives that you want a language with reified types, losing that reification with generics creates awkward cases in the languages and prevents possibility for optimization.
- bunderbunder 8y agoThey're not erased all the way, they're only erased down into the root type for all objects. So you've still got some type information left (namely, that it's an Object), and any types that are not Objects are officially banned from the generics system. Hence the need to dress them up as washerwomen and sneak them in through the service entrance.
- slavapestov 8y ago> This is another of those unfortunate implications of Java's having disappeared into this ugly chasm between static and dynamic typing. It doesn't fully erase types, so you can't do like C++ or Haskell do and just generate a completely different type, because it wouldn't be compatible with any functions that work with the generic type. Full monomorphisation is not compatible with separate compilation though.
- paulddraper 8y ago> Contrary to popular belief, Java's choice of erasure was not dictated by backward compatibility concerns but because erasure is a sound approach for type system representation. That statement is obviously wrong since Java did not choose type erasure. https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#getClass-- https://docs.oracle.com/javase/8/docs/api/java/lang/Object.h... In Java 5, generic types were added. And those Java chose to erase. So Java chose both: to reify and erase.
- int_19h 8y ago> Contrary to popular belief, Java's choice of erasure was not dictated by backward compatibility concerns but because erasure is a sound approach for type system representation. I wouldn't call it a "sound approach for type system representation", when it can't even consistently represent the fact that generic interfaces instantiated with different type parameters are different interfaces. I mean, it's obviously true given that any parameter-dependent method signatures are different, yet you can't implement Foo<Bar> and Foo<Baz> on the same class. > Reification also comes at a cost: performance What's the performance cost of reification? When comparing C# to Java, the only thing I can think of is that C# has an advantage in performance, because, due to generics being reified, its JIT can compile instantiations separately.
- yawaramin 8y ago> you can't implement Foo<Bar> and Foo<Baz> on the same class. Works for me: import java.util.List; class Test { public void setListBoolean(List<Boolean> list) {} public void setListString(List<String> list) {} public List<Boolean> getListBoolean() { return null; } public List<String> getListString() { return null; } public static void main(String[] args) {} }
- saagarjha 8y agoYour functions are named differently, though.
- int_19h 8y agoYou're using it, not implementing it. Try: class Test implements List<Boolean>, List<String> { ... } For another example, try your snippet, but rename setListBoolean and setListString to just setList (so that they're overloads).
- yawaramin 8y agoOK I see what you mean now, but that is the combination of type erasure and allowing method overloading that is causing the issue, not the erasure itself. For example, look at a language that doesn't allow overloads, like OCaml. Its types are fully erased, allowing very efficient compiled or transpiled code, e.g. https://reasonml.github.io/en/try?rrjsx=false&reason=LYewJgrgNgpgBAFRgZwC5wLxwN4Cg5yzrIyoAyAlmgBRRWoBch91aAThQHYDmAlL5jgApZADooIbgCZq+AnABEAZVLM0CgDRyCdNHN4BuXAF8jQA https://reasonml.github.io/en/try?rrjsx=false&reason=LYewJgr...
- naasking 8y ago> Contrary to popular belief, Java's choice of erasure was not dictated by backward compatibility concerns but because erasure is a sound approach for type system representation... ...for languages that don't have casting and have correct variance. Java fails on both.