Hacker News new | ask | show | jobs
by DarkNova6 1 day ago
What I love the most is the sheer amount of thought and philosophy put into Valhalla. It transcends the binary understanding of object vs value and actually defines 4 distinct buckets:

1: Classical Object

2: Object without identity

3: Atomic Value

4: Classical Value (Tearable)

Each bucket has clearly defined performance characteristics and semantic constraints. So depending on the nature of your data, you can always get some benefit from values even if you couldn't go all the way. This is a work of art.

2 comments

It's work of art and a work of science, I'd say. Programming language dev needs both, and I think Java has learned how to do both, at least compared to its messy early years.

On the note of science, I'll credit Java's maintainers for treating their language as a technology and not merely as a product. Many languages respect the real-world physics of computers to stay relevant. Few respect the "metaphysics" until weird bugs keep emerging in the compiler and ecosystem. Bugs that can't be solved with more building, engineering, or even design. Because those bugs are not defects; they come from the concepts & axioms of the language itself, not its implementation.

this comment reads like a parent who can’t help but love their child unconditionally and uncritically.

That’s a lot of complexity a lot of other languages don’t even need. It’s great Java designers have managed to shoe horn something in, but it’s all because of misdesigns 30ish years ago mispredicting of computer architecture.

I think you've misunderstood, because not only would this have been the right design if it had been in Java since day one as it's in line with the philosophy of the platform, it's also simpler than in other languages.

The idea is that instead of controlling memory layout and referencing directly, you communicate your intent: do you care about this value's identity or not? Do you need atomicity or not? Do you need nullability or not? Once the intent is clear, the compiler is free to choose the most appropriate and efficient layout for the particular value at the particular use site. In other words, you say what semantics you're interested in rather than how to implement them at the lowest level.

This opens up optimisation opportunities that are lost when the programmer directly controls the representation rather than the intent. E.g. in other languages you may say whether you want to pass some value by reference or by value. Here the compiler is free to say, well, if identity and nullability are not needed here, I can either pass by value or by reference, and I'll do whichever is more efficient.

And by the way, your point about early misdesign (whether it applies here or not) also inverts the desired state. Every language makes decisions that will be suboptimal in the environment some time later, and Java certainly has its share (its mutability and nullability default; how it treats serialisation). Rust, for example, was first designed twenty years ago, and some of its fundamental decisions reflect the state of the world at that time (it went all-in on some C++ premises that seemed fine 20 years ago). But since important codebases often outlast the outdatendness of early language decisions (your OS and your browser are running some >30yo code and/or affected by >30yo design decisions), one of the things most important in a language isn't the decisions it makes early on - some will prove "wrong" while your codebase is still alive and kicking - but how well it adapts and evolves. So when you pick a language for an important project today, the language's current state will end up mattering less than how the language evolves in the future. The question asked isn't "will I like this decision today?" but "will I regret this decision ten years from now?" Java is one of the languages with the lowest "regret factor", possibly lowest of them all.

While I agree with the comment being overly-praise-y, this is complexity that any multithreaded language with mutability and reasonable sanity/safety desires (but without intrusive compile-time rules a la Rust) has; others just might pretend some of the options don't exist / aren't desirable. (..and value objects, as landed in the PR, doesn't yet have tearable objects)
I think it really highlights how important it was to have atomicity and integrity by default because even here people will handwave away any such concerns as if they don’t exist.
Your comment makes no sense to me, but I must grant that there is a lot of bad reporting about Valhalla and I’ve been following the mailing lists for well over 7 years now.

Nothing, absolutely nothing about the design is a compromise that would detract from the project if it was for any other language.

You could judge them for bringing “complexity to an easy topic” but it really is far from that and the idea of a value type being a distinct dichotomy from an object is just a convenient tradition.

The push for immutability and value-ness has been going on for a long time and the motivation of the project was to bring performance benefits that align with semantic statements about the underlying data type. Which is of course a more nuanced take than “go value, go faster”.

Classical object, object without identity, atomic value, and classical value are not simplifications that you’d want in other languages. Rust, Haskell, Python - none of them need or would benefit from any of this.
Because?