6 ms·
I know its a faux pas in the Java world to acknowledge the existence of .NET, but how does this differ from .NET structs? Value types, generic specialization,
by torginus 4mo ago
I know its a faux pas in the Java world to acknowledge the existence of .NET, but how does this differ from .NET structs?
Value types, generic specialization, boxing - a quick skim makes it looks like they picked the same choices.
- rf15 4mo agoFunctionally they don't - java is just catching up with (by now) ancient practice. The false dichotomy of > A struct in C# has identity and mutation, so the semantics of copying on assignment or passing have to be precisely defined, which gives a heavier model for the programmer and less freedom for the runtime. Doesn't really match with what they're describing. While yes, it will not have identity in a java class ref sense, it of course will still have identity in being a unique structure in memory at a certain address. This is just splitting hairs about Java nomenclature.
- torginus 4mo agoI don't wanna badmouth Java people, but how they push the idea that this thing is some sort of genuine breakthrough that took multiple PhDs years of cutting-edge research to implement, when in fact they basically copied what .NET did from basically year 1, is not a good look. Again, not trying to turn this into a .NET vs Java thing, I'd have been much happier if they reached some new and interesting conclusions.
- misja111 4mo agoThis is exactly what made it so difficult. It is much easier to have a feature like this from year 1 than to add it to a language that has grown and evolved for 18 years already.
- rf15 4mo agoI agree with this sentiment. The work they put in deserves a lot of respect, and took a lot of effort, no doubt. It's just the framing they push to the public that could use some work.
- gf000 4mo ago> genuine breakthrough Well, it is - because they had to make it with almost perfect backwards compatibility for one of the most popular languages with trillions of lines of code produced over decades. Sure, adding it to a new language is not hard. Adding it to Java which has primitives, generics and boxing, finding ways that seamlessly cover the differences between objects and primitives, while trying to plan for the future is hard. As a general note, if you come to the conclusion that one of the best designer teams on Earth "basically copied what .NET did from year 1 is not a good look", then maybe your mental model needs adjusting on how these stuff works? Java has a public mailing list, you can browse through the related discussions. Implementation is the least of these things. But I can assure you they most definitely know what they are doing.
- sysguest 4mo agoidk maybe java should adopt something similar to rust's "edition"?
- gf000 4mo agoCorrect me if I'm wrong, but Rust editions are a source code-level feature. So given you have the source code of newer and older rust code, you can compile them together. That's materially distinct from Java's model of basically dynamic loading already compiled class files. Though class files do have "editions", and there are extra code to deal with different versions. But still, it should be possible to e.g. send a new value class to an old library's class that has never heard of them, and that should just work.
- simonask 4mo agoThe important thing is that Rust editions affect semantics and name resolution. In such an analogy, JVM bytecode is the equivalent of Rust code - various semantics are baked in, but stuff like name resolution isn't (at least not completely).
- tsimionescu 4mo agoExcept of course they are breaking backwards compatibility, in relatively subtle ways, for anything that uses the standard library wrapper types. So every use of Integer, Boolean , etc is an opportunity for either a compilation error or a runtime bug.
- coldtea 4mo ago>I don't wanna badmouth Java people, but how they push the idea that this thing is some sort of genuine breakthrough that took multiple PhDs years of cutting-edge research to implement, when in fact they basically copied what .NET did from basically year 1, is not a good look. Oversimplifying a big semantic and backend change to a huge codebase on which some of the most crucial customer and government and business systems depend on, and which has to be made as seamless, correct, and performant as possible, to "they just copied .NET", just because .NET has the same functionality, is an even worse look. It's a "HN "Dropbox is just rsync + some scripts"-style bad look.
- DarkNova6 4mo agoThe article is shit, the actual concept and roadmap goes well beyond the capabilities of C# or the CLR.
- oddx 4mo ago> it of course will still have identity in being a unique structure in memory No, it will not. The design allows multiple objects to share one structure in memory across multiple records, or not have such a structure at all (see Scalarization in the article).
- rf15 4mo ago> The design allows multiple objects to share one structure in memory across multiple records, or not have such a structure at all Yes. I fear you are missing the point.
- _old_dude_ 4mo agoThe article has a section about that. For me, a struct in C/C# can be modified and is passed by copy while a value class can not be modified and is passed by value. I do not think you can do stack allocation in Java.
- layer8 4mo agoI don’t see a difference between pass by copy and pass by value. The mutability difference is that part of a struct can be modified in place, which value classes can’t: the value of a complete value-class variable (or array slot) can only be modified (reassigned) as a whole. This is presumably because object references to value-class objects can be created, and those objects should be immutable so their identity doesn’t matter.
- _old_dude_ 4mo agoI think pass by copy is a consequence of being modifiable. The other solution is to stack allocate and pass a pointer but as i said, unlike in C#, i do not think it's possible to do that in Java. In Go, you can stack allocate but when you send a pointer (that escapes), the compiler will heap allocate the object.
- layer8 4mo agoMy point is that pass by copy and pass by value do the same thing, they copy the value representation. In other words, pass by copy means exactly pass by value.
- gf000 4mo agoActually, Java only has pass-by-value, even for reference types. (The same way as C does). People really misuse/misunderstand this term: Java objects are passed by their pointers ("references") being copied. The alternative is pass by reference, which is done by e.g. c++, rust, who actually have references (Java doesn't). A good litmus test is whether you can write a swap method that actually changes your local variables.
- DarkNova6 4mo agoC# actually has a fair amount of gotchas and Java aims to make these explicit. So where C# mostly copied C from a low level perspeCtive, the Java guys approached this high level and analyzed in detail which constraints give you what kind of benefit. So where in other languages, the struct/class taxonomy is binary, Java allows more granular control, reflection the semantics of the underlying domain. Snd as it turns out, structs have a wide range of footguns, especially in a parallel context.
- jaen 4mo agoCould you actually explain/exemplify any of the gotchas and what's been made better (or is this just handwaving)?
- bbg2401 4mo 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 4mo 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 4mo 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 4mo agoI made a comment on my understanding of the difference in implementation here: https://news.ycombinator.com/item?id=48606173 https://news.ycombinator.com/item?id=48606173 The ramifications for backwards compatibility is that the JVM won't have CLR features such as stackalloc (allocation of blocks of memory on stack), ref parameters (pass-by-reference of stack allocated value types), and all the other low-level/high-performance programming features available in the CLR.
- gf000 4mo ago> allocation of blocks of memory on stack) Why couldn't it be done? Like sure, it won't happen in every case (e.g. too big value classes), but for a typical local variable of a value type, it's a trivial optimization to make it stack allocated. Even now it happens quite often (requires escape analysis), but the semantics change of value classes allows for it to be done "freely".
- kuhsaft 4mo agoC# stackalloc returns a ‘ref struct’ which has certain restrictions and would be a Q-world type. Java chose to go with an L-world implementation where everything is still a reference type on the heap, but memory management is more efficient via flattening. That’s why it’s a ‘value class’ and not a ‘struct’. Primitive wrappers are scalarized into registers. Stack allocated value types would have different semantics and is incompatible with the L-world implementation. Sure, they could implement it, but it would be the Q-world implementation that they decided to forego. They can do automatic stack allocation for optimization via escape analysis as you mentioned. But, stackalloc is user allocated. https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/ref-struct https://learn.microsoft.com/en-us/dotnet/csharp/language-ref...
- kuhsaft 4mo agoThe 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, and they can be scalarized like C# structs. Java ‘value class’ only flattens if the total size of the class data fits within an atomic read/write op. You can force it to flatten, but you may have tearing like C# struct.
- kuhsaft 4mo agoEven closer would be a C# ‘readonly record struct’. Though, it would be allocated on the stack unless you box it.