4 ms·
Think of all the places where you need to pass in an explicit type to a Java class to workaround the fact that the types are erased (list.toArray() being the ca
by kllrnohj 9y ago
Think of all the places where you need to pass in an explicit type to a Java class to workaround the fact that the types are erased (list.toArray() being the canonical example, but reflection uses hit this a lot as well). That's the downside.
The only benefit to the erasure model is it's easier to implement for the runtime.
- KMag 9y agoNote also that Java does have reified generics, but only for arrays. The designers of the JVM from early on did realize the advantages of reified generics. Type erasure is not some principled stand being made by the JVM.
- kbsletten 9y agoWell, really their hand was forced because they needed to be able to specialize all of the array-of-primative types. It's not as much they saw the advantage as they couldn't imagine a language where you can't express `byte []`. But the point stands that they could have realized that `ArrayList <byte>` is almost as fundamental and created refied generics for user-defined types as well.
- KMag 9y agoThey could have had type erasure for all arrays of non-primitives. Their hand was not forced.
- masklinn 9y ago> Note also that Java does have reified generics, but only for arrays. By that count, so does C.
- Sharlin 9y agoC has no runtime type information at all. Java knows the difference between Integer[] and Float[] at runtime but not between List<Integer> and List<Float>.
- TheCoelacanth 9y agoJava has generics but they are only reified for arrays. C has types that are only generic in the case of arrays. There is a difference. In Java I can write this function <T> String getTypeOfArray(T[] arr) { return arr.getClass().getComponentType().getName(); } and that will return the name of type T at run-time. If I instead of T[] I use List<T>, getComponentType will return null and there is no way to access what type T is at run-time. At compile time List<T> and T[] behave the same, but at runtime the List loses what type if contains. In C I can't write a function with that signature at all because it doesn't support generic functions.
- seanmcdirmid 9y agoInterop is another advantage of the erasure model. Getting a version of Scala to run with reified generics on the CLR is a huge, perhaps impossible, undertaking. And if you can't do that, interoping with generic C# code becomes really hard. On the other hand, Scala interoping with Java code, generic or otherwise, is much easier.
- matthewwarren 9y agoI've heard this argument a few times now, it's an interesting point, having 'reified generics' imposes a tax on any language that wants to use that runtime. Here's a few other examples of the same point, https://twitter.com/jon_cham/status/969929683587432450 https://twitter.com/jon_cham/status/969929683587432450 and https://twitter.com/headius/status/958371298975080448 https://twitter.com/headius/status/958371298975080448
- noblethrasher 9y ago> Interop is another advantage of the erasure model And, in the case of F#'s type providers, it means not having to generate zillions of types when coding against some huge schema. But, on the other hand, it does give you the option to do so.
- seanmcdirmid 9y agoIf the bindings are reference types, the CLR will economize their representations as long as they don't have any static state, I think. I'm not sure if F# is leveraging the DLR, but there is a lot of fun that can be had there in generating types on the fly, on par with the most dynamic languages out there. It is too bad that it has been nerfed with the UWP/AOT compilation push.
- noblethrasher 9y ago> If the bindings are reference types, the CLR will economize their representations as long as they don't have any static state, I think. Yep, I knew about that, but type providers don't necessarily generate generic types. So, I meant something a bit different. As you know, If Foo<T> is an ordinary generic, then T must be a CLR type, which is to say that it must be code that was somehow turned into a CLR type (usually by a compiler such as C#). But, if Foo<> is a type provider, then arbitrary code of an arbitrary language can go in between the angle brackets (which is why type providers can accept strings). Essentially, each type provider is a compiler, but the code that is generated must be expressed (or "wrapped", if you will) as a CLR type. But these types need not be generic (and usually aren't, I think). So, not having erased types in F# is akin to having a compiler that can't generate loops or subroutines†. †(Perhaps a better analogy is a compiler that can't eliminate tail-calls, since erasing everything to a certain base type (that F# lets you choose) is kind of like reusing stack frames vis-à-vis the analogy)
- lmm 9y agolist.toArray() is only a problem in Java because arrays aren't erased. Mixing erasure and non-erasure in the same language is a problem, but it's not a problem with erasure.