5 ms·
> but Java has a lot of mistakes baked into the language and interfaces that can't be removed without potentially breaking a lot of stuff Absolutely true, but
by pron 8y ago
> but Java has a lot of mistakes baked into the language and interfaces that can't be removed without potentially breaking a lot of stuff
Absolutely true, but so does C#. In the end it turned out that .NET's reified generics were a mistake (which makes language interop on .NET painful), and more recently async/await.
- tomp 8y ago> In the end it turned out that .NET's reified generics were a mistake Do you have any resources that explain this point further? Reified generics have often been praised as the thing that CLR got right (and JVM got wrong). I never understood fully why that is, especially since other languages with generics (e.g. Haskell and OCaml) don't have anything reified (although in all honesty also don't have RTTI so it's really not necessary).
- pron 8y agoErasure makes it easy for Java, Kotlin, and Clojure share code and data structures without costly runtime conversions. Languages like Scala and F# have had trouble implementing features on the CLR because of reification, and take a look at what Python and Clojure on the CLR have to go through for interop. I know some people think that say they like reified generics in C#, but those are mostly people who aren't aware of what cost to the entire ecosystem they're paying in exchange to what is a minor convenience in C#. BTW, reification of reference-type generics is not to be confused with specializing collections for value types ("arrays-of-struct") an extremely important feature that CLR indeed has, and Java is now working on getting.
- eropple 8y ago"Mistake" is a strong word, and I would disagree with it. But when building extensible libraries and systems I do often find myself wanting to pass around a List<Something<?>>, which isn't doable without writing a second generic interface or the like. On the flip side, in Java (or, these days, Kotlin), a type-erased generic can be mediated more easily because passing a Class is easier than adding a second interface. Part of it is that a lot of that stuff is gamedev-related, for me. It's not the biggest thing in the world, but for a lot of the stuff I find myself writing in C#, I find myself wishing for type erasure to make throwing data around a little easier. On the other hand, though, when writing web stuff on the JVM--I absolutely will not waste my time doing this in .NET, ASP.NET Core is not very good and EF Core is awful--I often wish for type reification, so it's just a horses-for-courses thing.
- int_19h 8y agoGenerics interop just fine on .NET, and async/await had become a starting point for similar designs in many other languages. I don't think you'll find many people who actually write code in that ecosystem agreeing with either of those claims.
- pron 8y ago> Generics interop just fine on .NET They really don't. They have posed severe restrictions on features in languages like Scala and F#, and take a look at Clojure, Python and JS interop on the JDK as opposed to .NET. > and async/await had become a starting point for similar designs in many other languages. And it's a mistake in most of them. Java has copied some of C's mistake, C# has copied some of Java's, and others may copy some of C#. Every language/runtime both repeats others' mistakes and adds a good helping of its own. > I don't think you'll find many people who actually write code in that ecosystem agreeing with either of those claims. I can only express my own opinions (and I think reified generics, as implemented in the CLR, is a far bigger mistake than async/await, which only affects the C# language), but I am far from being alone in having them. Also, I have no doubt that async/await is an improvement on the previous situation, which is why people like it, but nevertheless I think it's a mistake as there are alternatives that are more convenient, more general, and have less of an adverse impact on the language (e.g. Go's goroutines).
- int_19h 8y agoWhat are the restrictions on F# that were posed by them? Given that Don Syme was the one who originally designed them, specifically with a mind for cross-language use (which is why they got stuff like variance long before C# supported it), this is a surprising claim. In fact, I recall Don saying something along the lines of, if CLR did generics with erasure like Java, F# probably wouldn't be where it is today. I saw the link to Clojure page you posted in another comment, but I don't see any fundamental problem with generics there. Yes, if you're invoking a statically typed language from a dynamically typed one, you have to occasionally jump through hoops when dealing with things like method overloads that require types to distinguish. The same goes for Python. I have actually used Python embedded in C# more than once, with interop both ways, and in practice it "just works" most of the time. Conversely, I don't see why statically typed languages should surrender valuable type information (and associated perf and expressivity gains) for the sake of convenience of dynamically typed ones, especially on the platform where static typing is the norm, and libraries are expected to be designed around it. As far as async/await vs Go's goroutines - since we're talking about language interop, how many languages can Go coroutines interop with? Async/await easily flows across language boundaries, as you can see in WinRT - any language that has the notion of first-class function values can handle that pattern. Goroutines are essentially a proprietary ABI. And the worst part is that once the language has them, all FFI has to pay the tax to bridge to the outside world, regardless of how much you actually use them. It may be an argument for standardizing some form of green threads on platform ABI level, so that all code on that platform is aware of their existence and capable of handling them. Win32 tried with fibers, without much success. Perhaps it was too early and the design was too flawed, but it's not encouraging.