6 ms·
Could you actually explain/exemplify any of the gotchas and what's been made better (or is this just handwaving)?
by jaen 3mo ago
Could you actually explain/exemplify any of the gotchas and what's been made better (or is this just handwaving)?
- bbg2401 3mo agoWhy would you presume the parent is "just handwaving"? It's odd how people in the .NET community struggle to earnestly engage in conversation with Java folk. The reverse isn't true.
- kuhsaft 3mo agoThe gotcha is the potential boxing of structs onto the heap, but that can be avoided using `ref struct`s. https://news.ycombinator.com/item?id=48599273 https://news.ycombinator.com/item?id=48599273
- cogman10 3mo agoPart of the reason Java hasn't reified generics is because C# did and it was a real big headache that also limited non-C# languages on the C# runtime (CLI?). Everything had to be recompiled to work with newer C# runtimes. While it's pretty easy to run a bunch of language on the JVM (Javascript, python, ruby, clojure) doing the same for C# is somewhat a nightmare, particularly for non-type aware languages. For example, Imagine you have an api like `void do(List<Foo> foos)`. In the erasure environment of the JVM that looks like `void do(List foos)`. From python it's pretty easy to call with a `foos = [Foo()]`. But not so much if your python implementation needs to figure out how and if it can coarse it's `List` type into a `List<Foo>` type.
- kuhsaft 3mo agoI don’t think that’s the case. You can absolutely implement a type-erased language on top of the CLR. Your language will just have the same constraints of a type-erased language like Java. Having reified generics in the CLR just lets you store more type information. There isn’t much of a trade off for CLR end-users. Compare this to the constraints and workarounds that Kotlin and Scala have due to type-erasure on the JVM.
- cogman10 3mo agoYou CAN do it, but it's much more difficult. And as far as I'm aware, both kotlin and Scala don't really suffer due to type erasure.
- kuhsaft 3mo agoI mean, the language is what it is. But, it definitely constrains the language developers. Especially when considering interop with other JVM languages. That being said, it is easier to write a language on top of the JVM with good interop, since there are less ways to implement features. Essentially, your language has to interop with Java. And it is harder to have good interop between CLR languages because there are more ways to implement features. Essentially, your language has to interop with C#.
- pregnenolone 3mo ago> Compare this to the constraints and workarounds that Kotlin and Scala have due to type-erasure on the JVM. The creator of Scala disagrees: https://youtu.be/Xn_YpUtXWT4?t=850 https://youtu.be/Xn_YpUtXWT4?t=850
- kuhsaft 3mo agoNot necessarily. You can ignore the reified generic system in the CLR and monomorphize it in the CIL output for your language. Debugging for users is usually a nightmare though due to the monomorphization. The benefit of a type-erased runtime is the interop between the languages built on the runtime. The monomorphization of CLR generics is what NativeAOT does, though it doesn't support some C# features. TypeScript is essentially C#, but with type-erasure and lacking the low-level struct & pass-by-reference features. I do think the C#/CLR struct implementation is better though.
- WorldMaker 3mo agoIronPython did just fine with reified generics.
- kuhsaft 3mo agoThere's also https://github.com/ikvmnet/ikvm https://github.com/ikvmnet/ikvm that converts Java bytecode to CIL; essentially Java on CLR.
- pjmlp 3mo agoActually no it didn't, DLR was created exactly to support dynamic languages on the CLR. Nowadays largely abandoned, and I think not everything survived the transition from .NET Framework into modern .NET.
- kuhsaft 3mo agoYeah, that’s a different issue. Statically-typed languages, including type-erased languages, are fine on the CLR. Dynamically-typed languages are a different beast. I suppose DLR would be comparable to GraalVM/Truffle. The difficulty of implementing a dynamically-typed language directly on the CLR and JVM are about the same. Though, it would probably be more efficient on the CLR with access to lower level operations for memory management. I think an interesting project would be to implement a CIL interpreter on GraalVM.
- pjmlp 3mo agoDLR inspired the addition of invokedynamic opcode on the JVM, which is actually the foundation for how lambdas get generated, many still think nested anonymous classes are used. GraalVM already handles LLVM bitcode, much cooler than plain MSIL. And here there is another example where Java ecosystem ends up being better. MSR had a compiler framework similar to GraalVM, called Phoenix, it was going to replace VS, LLVM style, instead it died and what is left are a couple of research papers.
- cogman10 3mo ago
- DarkNova6 3mo agoI've been let down by structs in C# repeatedly. First of all, there are no constructor guarantees and you can never fully avoid them representing an illegal state. Which, wouldn't be so bad if there was some kind of post-construction validation, but this also isn't part of the language. This is fine if you hand-roll all your code yourself, but I often use mapping libraries to lower the code footprint and the problems resulting from schema changes are subtle and fly under the radar. This is different from classes with hard construction guarantees, which Java would offer with their "integrity by default" mantra. Where you can opt out of integrity for performance benefits (which is also part of the design). And Nullability in C# is an absolute nightmare. The type system has completely different rules for nullable types that generalize over classes and structs and there is no generic such as a "Nullable type". It's just lots of minor annoyances that don't form a cohesive whole.
- DarkNova6 3mo agoIt is beyond me why I would get downvoted for legitimately pointing out shortcomings. I find it honestly frustrating how some people believe that “their language is best”. Until you point out real existing inconsistencies…
- kuhsaft 3mo agoI hate to say it. But thats user error. The struct paradigm is different from classes. Structs are meant to be plain-old data types; simply a typed span of memory. Structs are values, classes are entities with encapsulation. The shape of the state would be structural. Whether or not the data in that shape is valid is behavioral. Structs are useful when working with spans of memory. Another example of a good usage of struct is Guid, which is 128 bits of data packed together. The C# equivalent to Java ‘value class’ would be a class with a struct encapsulated for data. The data is flattened and allocated on the heap like Java. Similarly, escape analysis could stack allocate the class at runtime.
- DarkNova6 3mo agoThis is what makes the nuances of Valhalla's Value types so compelling. The idea are granular structs with "Integrity by default", where you can selectively give up constraints on class design to get performance characteristics. Structs in most languages simply bunch a couple constraints together to get another set of performance benefits, but there's no law stating that they couldn't be singled out. In the design of Valhalla, it states that types can come in 4 buckets: 1: Fully identity classes (total control, mutable) 2: Value Based classes (no mutability, but full integrity and dense memory layout) 3: Implicitly constructed values (forced empty default constructor for swift bulk array initialization) 4: Tearable Values (No cross-field integrity during runtime for parallel access) And I bet that for a vast majority of developers, #4 will come to a shocking surprise, thinking "values are threat safe" because they are told to use immutables. This way of splitting up structs is the real interesting part of Valhalla, but this shitty AI-generated article buries everything interesting.