Hacker News new | ask | show | jobs
by throwaway4good 1874 days ago
"Huge disadvantage that matters to me is that record fields cannot be mutated. It makes the records much less useful."

No. It makes them much more useful.

1 comments

Well it means that the second you need a setter you can't use records so all the boilerplate remains.
You are supposed to create a new copy with some of the fields changed. Just like you do it with the java.time.* classes and others.
Yet the only mechanism for this is error prone or relying on mountains of boilerplate.
Instead of changing few bytes, now I have to copy hundreds of bytes around and add more stuff for GC to collect.

Well, they have to obey Wirth's law, I guess.

I mean, you do realize that you're writing Java code right? If you want ultimate low level optimization and control then you're already about ten miles too far downstream to make that turn. Also, I'm guessing the copy overhead is more than offset by the JVM being able to do better optimizations around these data structures.
Structs with mutable fields is hardly “ultimate low level optimization”, it’s something a lot of programmers still use as a matter of course. (I say this as a fan of immutable data!)

Ultimate low-level optimization in Java would be more like packing your structure into arrays of integers - which is something people actually do in Java. Just because you’re using Java doesn’t mean you don’t want your code to run as fast as possible.

I don't know if the JVM developers have actually implemented this, but since records are immutable, there's no reason why a copy couldn't share memory between the instances.

The major downside is that could ruin cache locality and make passing the instance across a FFI boundary require a copy.

Another optimization would be that the JIT (or even perhaps javac) could notice cases where you make a copy (with one field changed) of a record and then never use the original reference again. If the JIT (or javac) can prove that no other bit of code holds a reference to the original record, it can reuse and mutate the original one instead of making a copy. I don't know if this optimization is or will be implemented, of course.

Either way, I expect the overhead you mention ends up being worth the benefits of immutable data. (That's been my experience using Scala, anyway.)

This has been argued ad nauseam around the time Scala started gaining traction because scala's collections are grouped into immutable and mutable. The consensus at the time is that the GC overhead is well worth the ability to parallelize computation.
You have to copy less than you think. Because the data is immutable, you can share everything but the changed fields.
Then you've invented mutability without references/identity. Except those are desired properties for data classes, unlike for value classes which have such semantic difference.

Btw Kotlin allow to make immutable Java records too so clear winner.

Not sure what you're getting at. Immutable means exactly that. If you hand out an object, then do a copy change, that change isn't reflected in the object you gave to another method/thread/fiber/etc. Immutability doesn't mean application state never changes; it means that a single reference will always point to memory that hasn't changed.
Or you know, the JIT will trivially optimize away the old class if it is reassigned to the same variable, as you would use it inside a loop. How do you think the litany of FP languages work? Like Haskell, Scala, Clojure?
It can be done in theory, but the JVM does nothing of the sort right now.
False. The JVM already does quite a good job with escape analysis, and record types just add extra semantic information to potentially further improve the situation.
That's a theory not happening in practice. In practice Java programs are slow and memory-hungry because of those issues when some people think that it's cheap to create small objects or that escape analysis will solve their issues without verifying that it works for their case.
Most of the world’s server applications would like to disagree with you.
Java isn’t perfect. But you underestimate the amount of software written in it. Or even things like Python and JS which are a lot more basic but have similar elements in regards to their memory model. What do you use?
GC is there for a reason, unless you do HFT, use it to your advantage.
You write java and worry about bytes copied?
Yes, I do. Java could be quite fast if you won't slow it down on purpose.
Why would you need a setter for a data class? They add no value there.