8 ms·
> Ultimately, an erasure model of generics would have been adopted, as for Java, since the CLR team would never have pursued a in-the-VM generics design withou
by krat0sprakhar 9y ago
> Ultimately, an erasure model of generics would have been adopted, as for Java, since the CLR team would never have pursued a in-the-VM generics design without external help.
Can someone explain why "in-the-VM" generics design is better than the erasure model of Java?
- rusbus 9y agoIn Java, you can't make runtime decisions based on the generic type of an object. Eg. you can't have a List<?> and check to see if it's a List<Foo> or a List<Bar> -- that information has been erased. You could look at the head of the list to make that determination, (because the List members still have a concrete type), but that isn't a general purpose solution. Languages like Scala use manifests to preserve the information but it's a major kludge.
- yarg 9y agoLooking at the head of a List does not work. The class of that element is within the scope of <? extends ListType>, an is not necessarily not ListType.
- rusanu 9y agoNot to mention that an empty list still has a type...
- yarg 9y ago*and is not necessarily ListType. Idiot.
- Twisol 9y agoFor the downvoters, the author is correcting themselves after the edit window. It's clearly self-deprecating humor, not a personal attack.
- Groxx 9y agoTo spell this out so it's a bit more obvious, given a Thing at head of a list, you could have: - a List<Thing> - a List<ThingSuperclass> - a List<? extends Thing> - a List<? super ThingSubclass> - a List<IThing> - a List<ILiterallyAnyImplementedIFace> - a List<IHaventForgottenInterfacesCanExtendOthers> - a List<Object> - a List<I'm probably forgetting some possibilities> And you have no way of knowing which it is. So yes, it's a boundary, which is significantly more than nothing. But far less useful than it feels like at first.
- Gibbon1 9y agoOne the way to looking at other things(tm) I found a blog post by a CS language researcher talking about type erasure. His two points. Being able to do type erasure is great because it means your language is coherent. (Don't need to do any nasty kluges in the run time) And then everyone ratfucks themselves by actually implementing type erasure, and now your language will never have good tooling and thus will die a lonely unmourned death. He commented that C/C++ has type erasure and it's also a massive kludge (via the elf format). No one will invest that much effort into a new language. tl;dr: Type erasure, it's great, don't do it.
- eeperson 9y agoWhat tooling do you think is missing due to erasure?
- Gibbon1 9y agoNot a CS person, but I think if you keep the type information pined to the object in memory then a debugger can use the object type information in memory to match it with the object's definition in the program. That makes creating a debugger easy. Imagine wanting to know what the object at address 0x34199920 is. If you have type info[1] you can cross reference the type info with 'generic array' and then do the same with element 2, address 0x34199920 and know it's a 'foo object'. [1] Say the first 4 bytes is _always_ a type index that the compiler or interpreter generates.
- cm2187 9y agoBut then what is the difference between a a collection of type object and a errasure model generic collection?
- kelnos 9y agoAt the VM/bytecode level, not much (if anything?). The benefit comes at compile-time, where the compiler can verify that you're putting the correct types into a collection, and that you're expecting the correct types out.
- SideburnsOfDoom 9y ago> At the VM/bytecode level, not much (if anything?). I don't think this is correct. In C# code at runtime, and in the bytecode, you can inspect types for metadata about their generic type params. It is present in the .Net bytecode. See https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/generics-and-reflection https://docs.microsoft.com/en-us/dotnet/csharp/programming-g... > When a generic type or method is compiled into (bytecode), it contains metadata that identifies it as having type parameters. from https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/generics-in-the-run-time https://docs.microsoft.com/en-us/dotnet/csharp/programming-g...
- cm2187 9y agoBut C# generics aren't erasure model collections are they?
- SideburnsOfDoom 9y agoNo, they are not. The point is, it is different at the bytecode level.
- shellac 9y agoYou've got that completely the wrong way around. An erasing compiler has full access to the type (obviously - it's doing the erasing) and so can verify whether you're putting the correct types in or out of a collection. Where erasure can cause issues is at runtime. For example: X isa List<Int> Even if X is indeed a list of ints that information isn't held at runtime, so the test can't be supported. Having said that in some respects this is a C# / Java ecumenical matter. Haskell, for example, doesn't bake types into output code so I suppose it erases even more that java, but it supports very rich polymorphic behaviour.
- kllrnohj 9y agoThink 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>.
- tehlike 9y ago2 main things: - Boxing/unboxing would not be an issue anymore, so you gain performance. - Runtime types are enforced: List myList = new List<String>(); myList.add(new Object()); In JAVA, this is ok. In c#, it throws.
- ygra 9y agoYou'd have to call the Java variant via reflection to show the difference at runtime, as the compiler would already enforce that myList.add(new Object()) won't compile. The point stands, though.
- tybit 9y agoI would say java and c# have both failed on your second point, separate to their respective VMs issues. It would be nice if mistakes like that were deprecated then eventually fixed, even if over many years/versions.
- eterm 9y agoTesting this, it doesn't throw in C#, it just doesn't compile because you can't declare a variable to be a List without declaring the type with it. If you specify myList as List<String> then it still doesn't compile.
- tehlike 9y agoFor c#, try compiling with IList instead of list. IList myList = new List<String>(); myList.add(new Object());
- seanmcdirmid 9y agoPerformance: you can get rid of all those bridge casts without the need for an inter-procedural analysis. However, since C# also supports structs, generic instances of structs can be (and most of the time are) inlined to realize struct performance benefits. Ease of programming: your generic type bindings don't disappear at run-time and can be used run-time logic decisions, basically violating Bracha's law (types shouldn't influence run-time behavior), but I found it incredibly useful for meta-programming reasons.
- quickthrower2 9y agoAs a Haskell aficionado I can appreciate type erasure and the idea that you don't need to know shit at runtime. However yes when using hybrid languages like C# you have to cheat sometimes. Although anything that uses reflection makes me cringe and there is the practical concern that analysis tools such as find all references etc. are of less use when there is stuff going round and reflecting on shit.
- daxfohl 9y agoThis seems orthogonal though. Just because a runtime uses reified generics, doesn't mean that it has to provide reflection on them. Is there something special that type erasure adds, that you couldn't have Haskell without it? From a layman's perspective it seems that Haskell could be implemented with either an erased or a reified generics model under the hood, without changing the public surface of the language. But is there something that type erasure enables that reified generics does not?
- masklinn 9y ago> This seems orthogonal though. Just because a runtime uses reified generics, doesn't mean that it has to provide reflection on them. It's not completely orthogonal as erased generics are annoying/problematic when the language does provide reflection/RTTI. So you've got 4 (reification x reflection) states 3 of which are fine: * if you have erasure and no reflection (Haskell) you're fine: you don't have runtime types but they don't matter/are inaccessible * if you have reification and reflection (C#, C++/RTTI) you're fine: you can access runtime types and have them * if you have reification and no reflection (Rust, C++/noRTTI) you're fine: you can specialise & discard types at runtime * if you have erasure and reflection (Java) you're fucked: you can access types at runtime, but many aren't here anymore > From a layman's perspective it seems that Haskell could be implemented with either an erased or a reified generics model under the hood, without changing the public surface of the language. But is there something that type erasure enables that reified generics does not? A simpler implementation.