3 ms·
Just about every programming language expert I've seen who's talked about Java generics says Java did a better job than C#. In fact, of all language runtimes th
by sreque 10y ago
Just about every programming language expert I've seen who's talked about Java generics says Java did a better job than C#. In fact, of all language runtimes that do generics, the .NET runtime is the only one that specializes. Examples of runtimes that do not specialize or reify generics:
* JVM
* Haskell runtime
* ML family of languages
* Modula-3
* Ada
The problem with specialized generics in the runtime is that they bake the type system of the language into the runtime itself, making the runtime more difficult to work with. Type erasure, for instance, makes it much easier to implement alternative languages on the JVM such as JRuby, Clojure, Scala, or Kotlin, than on .NET.
As another example, C# in 4.0 added the concept of generic type variance, which is completely at odds with specialized generics. To implement this feature, the C# language designers had to modify the underlying runtime itself and add special bytecode instructions for the feature. The feature itself is also incompatible with specialized generics, so when you use it you silently lose specialization.
In contrast, thanks to type erasure, the Scala language designers could easily add the same feature on top of the JVM as-is without needing Oracle to add special bytecode instructions.
Specialization has advantages for performance when doing number crunching with data structures and algorithms operating directly on integral or floating point data types. At the end of the day, though, if you really need performance for this very narrow field of use cases, you're probably not going to be using generic data structures and algorithms anyways. It takes an incredible amount of effort to build a data structure or algorithm that is both generic and also performant in all possible usage scenarios. It is however, much easier to build a data structure or algorithm that is specific and performant relative to your use case alone.
Case in point: when I was in college doing a NLP assignment that needed to be fast, my data structures were arrays of doubles because that was the easiest way to reason about and ensure performance.
- josefx 10y ago> In fact, of all language runtimes that do generics, the .NET runtime is the only one that specializes. As a C++ programmer I would mention templates as something similar. > The problem with specialized generics in the runtime is that they bake the type system of the language into the runtime itself, making the runtime more difficult to work with. When inheritance comes in to play Java ends up storing generic type information in the child classes. It even has to generate bridge methods since Runtime does not really deal with int compareTo( Comparable<? extends T> ) vs. int compareTo ( MyInteger ) . > if you really need performance for this very narrow field of use cases, you're probably not going to be using generic data structures and algorithms anyways An ArrayList<Integer> makes sense in very few cases and is extremely slow, 64 bit pointers to objects that contain useless metadata and a immutable 32 bit int. Sadly an IntList is neither generic nor is it compatible with anything that operates on List<T>s, which results in duplication of a lot of algorithms just to sort primitives. > when I was in college doing a NLP assignment that needed to be fast, my data structures were arrays of doubles because that was the easiest way to reason about and ensure performance. Case in point: In C++ std::vector<double> and the standard algorithm header take care of most of that. If there is some specialized implementation of some algorithm for double values then you can still use that without copy pasting the implementation of everything else.
- sreque 10y agoI purposely left out templates because I do not consider them to be the same as generics. Their is no "runtime" support for templates; templates are basically a glorified macro engine for creating new code based on type parameters. But yes, templates by definition specialize since they are creating new code every time they are instantiated.
- josefx 10y ago> Their is no "runtime" support for templates; At runtime any Java List is a list of Objects, you cannot distinguish an ArrayList<Integer> from an ArrayList<Double> both are a raw ArrayList. What runtime support do they have? > I feel bad for the C++ linkers that have to sift through all the template bloat to dedupe them :(. If you have a template used often enough you can declare it extern and force instanciation in a specific cpp file.
- sreque 10y agoThere actually is some basic runtime support for generics, just enough to avoid breaking the runtime. For instance, if I create a class MyList extends ArrayList<Double>, there actually is some runtime information that says MyList is an ArrayList<Double>, not just an ArrayList. You're right though that saying templates are different from generics is based on opinion, not fact. There's no widely-accepted definition of both that would separate them as distinct from one another.
- pjmlp 10y agoAda is compiler specific.
- MichaelGG 10y agoGenerics just bake a little bit more into the runtime; there's already a lot of the type system there. And it increases interop potential. I don't understand your point about Scala - they could always choose to use type erasure instead of any runtime-provided generics. F# implemented generics with erasure on the 1.x CLR, and used the runtime when on CLR 2. And this is the first time I've heard that the JVM is easier to target for non-Java languages. .NET has had multi-language support an official design goal, the JVM is just for Java. Even simple stuff like pointers, so you can do ref/out parameters. Or unverified instructions. The CLR is simply more all-around capable. I am pretty sure the CLR always supported variance, it was just unused up until C# 4.0. AFAIK, there haven't been any changes to the runtime bytecode since CLR 2.0, when generics were added. The performance benefits of specialization are pretty nifty. The Mono guys ported Android to C# and got quite the performance improvement on some code: https://blog.xamarin.com/android-in-c-sharp/ https://blog.xamarin.com/android-in-c-sharp/ - so that's existing code that got a perf benefit "for free" due to not using type erasure. Edit: A quick skim of the specialization proposal for Java[1] makes no mention of other languages. Just the general pain of integrating it in a compatible way. 1: http://cr.openjdk.java.net/~briangoetz/valhalla/specialization.html http://cr.openjdk.java.net/~briangoetz/valhalla/specializati...
- pjmlp 10y agoBrian Goetz sometimes refers to it on his presentations. As for multi-language support on the CLR, compared with the old 1.x days, there seems to be less focus on it. With C# getting most of the focus, followed by VB.NET and F# playing catchup. Also outside MSR, most researchers focus on the JVM, in spite of its caveats, and nowadays LLVM as well. ETHZ is the only one I am aware that also designs languages with CLR in mind. The Active Oberon successors, like Zonnon. There are some companies selling compilers for .NET, like Cobol, Eiffel and Pascal. Not sure how well they are doing it. Clojure also targets the CLR, but they don't seem to have a story for .NET Core.
- MichaelGG 10y agoIsn't that more a function of MS's hostility to other platforms, not technical reasons? If MS had been more open and friendly 15 years ago things might be different.
- whatever_dude 10y agoI can't speak about any of the programming language experts you've seen, but: > To implement this feature, the C# language designers had to modify the underlying runtime itself and add special bytecode instructions for the feature I think this argument is misconstrued. This is inherent to the way the CLR was designed. It is not meant to be something that is kept as-is in terms of the bytecode it accepts. It is constantly being improved upon. Most new language features to C#, F#, or other CLR languages mean an update to the CLR if they're related to a new feature in the abstract. While there's an argument to be made on whether this better than a more generic runtime, the point is that requiring a change to the CLR is not a big deal; that's part of their plan.
- sreque 10y agoIt should be plain to see that it would be much easier to implement your programming language on top of the CLR or JVM if you didn't need to request new features from Oracle or Microsoft to be added to the runtime. I remember one time someone proposed a patch to the JVM to add tail cail optimization and it was basically rejected or deprioritized into oblivion: http://mail.openjdk.java.net/pipermail/mlvm-dev/2010-October/002017.html http://mail.openjdk.java.net/pipermail/mlvm-dev/2010-October... These VMs are complicated machines and Oracle/Microsoft aren't going to risk modifying them unless it fits their respective agendas.
- tracker1 10y agoWhich is why I've been very happy to see .Net Core take the path it has... it's been much more open to outside collaboration even if the bulk is done by MS employees.