Live data from Hacker News

Making Lenses Practical in Java

chriskiehl.com

71–80 of 108 posts

Re: Making Lenses Practical in Java

#71
post #34

Earlier quoted context omitted.

The biggest thing missing from records that Lombok provides is withers.

In the works: https://github.com/openjdk/amber-docs/blob/master/eg-drafts/...

Strange how you consider property assignments from C# but only in the very limited scope of `with`.

Why not have all other lessons from C# like `{get; set;}` and object initialisation (among other things) syntax is beyond me.

(Well, "we don't adopt strategies [whatever that means] from less successful languages" is a reason I guess https://news.ycombinator.com/item?id=28985688)

Re: Making Lenses Practical in Java

#72
post #34

Earlier quoted context omitted.

In the works: https://github.com/openjdk/amber-docs/blob/master/eg-drafts/...

Strange how you consider property assignments from C# but only in the very limited scope of `with`. Why not have all other lessons from C# like `{get; set;}` and object initialisation (among other things) syntax is beyond me. (Well, "we don't adopt strategies [whatever that means] from less successful languages" is a reason I guess https://news.ycombinator.com/item?id=28985688 )

What I meant was that we don't adopt a feature just because some other language has it, let alone from languages that don't have the same philosophy as we do of trying to have as few features as we can get away with. Records are overall more valuable than properties (due to various reasons, from serialization to interaction with collections). But once you have records with "withers" the question becomes how valuable is it to also have properties. It doesn't seem like it would be helpful enough to overcome the drawbacks.

BTW, C# didn't add properties as a "lesson." Properties in C# and JavaBeans have the same pedigree: RAD UI composer tools of the 90s [1]. They came to C# by way of VB. So really, Java would be adopting a VB solution, and there needs to be a good reason for that.

[1]: https://en.wikipedia.org/wiki/Rapid_application_development

Re: Making Lenses Practical in Java

#73
post #40
post #19

Lenses are cool, but they make me wonder: how many different paths of a deep immutable data hierarchy are transformed in an application to make this abstraction worthwhile, as opposed to replicating the entire traversal at each location? If the number is small then, however cool, this abstraction may be more trouble than it's worth. Just because you can reify some concept in an elegant composable construct doesn't me…

Remember not to think about it "statically". If you're comfortable with lenses, then the cost of introducing more precise types and modelling all your states goes down, so you do more of it. E.g. maybe it becomes worth using a separate type for pre- and post-validation versions of some datastructure where before it wasn't, because you need to be able to traverse both versions with the same code, but now you can.

True, but that only pushes the question of value down the line.

I'm curious about lenses because Java did have a serious problem that required a solution: working with "simple" data correctly was difficult. The chosen solution was ADTs, so we did buy into that. But the approach being explored for transforming records (https://github.com/openjdk/amber-docs/blob/master/eg-drafts/...) only works one level at a time rather than for an entire path. So I wonder how valuable it would be to have a solution for paths. If the answer is that it's mostly valuable for an approach we haven't bought into yet, then we might not need to consider it just yet.

Re: Making Lenses Practical in Java

#75
post #67

Earlier quoted context omitted.

It can't but that's not due to the proposed solution for withers. The cause is Records themselves. Record are immutable on purpose and you want to add a mutation constraint whish will not play nicely. The proposed constraint will be triggered in this case : var r = retrieveFromDb(); (value is A) r = r.with(C) -> throw an exception But this only work if B is generated by the wither. If I deconstruct the record manuall…

>>My example above demonstrates a constraint that cannot be implemented in a constructor. >It can't but that's not due to the proposed solution for withers. This has nothing to do with withers. It can't be implemented simply because it is a constraint on a specific transition of state. There's no transition of state in constructor. >Record are immutable on purpose and you want to add a mutation constraint whish will…

I can't find anything in the linked eg-draft that would indicate that the error would "occur later". In fact, it explicitly says:

    Note too that if the canonical constructor checks invariants, then a with expression will check them too. For example:
        record Rational(int num, int denom) {
            Rational {
                if (denom == 0)
                    throw new IllegalArgumentException("denom must not be zero");
            }
        }
    If we have a rational, and say
        r with { denom = 0; }
    we will get the same exception, since what this will do is unpack the numerator and denominator into mutable locals, mutate the denominator to zero, and then feed them back to the canonical constructor -- who will throw.

Re: Making Lenses Practical in Java

#76
post #32

Earlier quoted context omitted.

> (e.g., "given a DOM node, traverse all of its children") you can use a library of transformations ... and write queries and transformations over arbitrary structures in a very compact way. But in Java you'd do that with reflection. So the question remains, how many such different queries/transformations you actually have (in the source code, where type checking is available, rather than user input) to make the effo…

Maybe you would rather do that with reflection, but I'd rather do something that isn't fundamentally the same tools that create security vulnerabilities. Every time you can not-use reflection is a win.

Records were specifically designed for safe reflection (and safe serialization). What causes security vulnerabilities is so-called deep reflection, i.e. the use of setAccessible, and can then violate various invariants. That's not what I'm referring to here. Reflection ≠ deep reflection.

Re: Making Lenses Practical in Java

#77
post #72

Earlier quoted context omitted.

Strange how you consider property assignments from C# but only in the very limited scope of `with`. Why not have all other lessons from C# like `{get; set;}` and object initialisation (among other things) syntax is beyond me. (Well, "we don't adopt strategies [whatever that means] from less successful languages" is a reason I guess https://news.ycombinator.com/item?id=28985688 )

What I meant was that we don't adopt a feature just because some other language has it, let alone from languages that don't have the same philosophy as we do of trying to have as few features as we can get away with. Records are overall more valuable than properties (due to various reasons, from serialization to interaction with collections). But once you have records with "withers" the question becomes how valuable…

> and there needs to be a good reason for that.

A year ago I already said all the good reasons. There are many reasons why things like Lombock exist. There are reasons why people loathe writing interminable chains of builder methods.

But sure. None of these are good reasons because something something Visual Basic.

What Java will inevitably end up with is a yet another half-assed approach that only exists for a small part of the language and is not applicable to the rest of it.

> BTW, C# didn't add properties as a "lesson."

That's not what I wrote. This is literally from your link: "Digression: learning from C#"

And look. Right below it, emphasis mine

--- start quote ---

The C# approach was sensible for them because they could build on features they already had (default parameters, properties)

--- end quote ---

And look. "Extrapolating from records" section basically says: Java has nothing, and will need to rebuild everything from scratch for this not to be a half-assed solution. Oh well.

Re: Making Lenses Practical in Java

#78
post #72

Earlier quoted context omitted.

What I meant was that we don't adopt a feature just because some other language has it, let alone from languages that don't have the same philosophy as we do of trying to have as few features as we can get away with. Records are overall more valuable than properties (due to various reasons, from serialization to interaction with collections). But once you have records with "withers" the question becomes how valuable…

> and there needs to be a good reason for that. A year ago I already said all the good reasons. There are many reasons why things like Lombock exist. There are reasons why people loathe writing interminable chains of builder methods. But sure. None of these are good reasons because something something Visual Basic. What Java will inevitably end up with is a yet another half-assed approach that only exists for a small…

> The C# approach was sensible for them because they could build on features they already had (default parameters, properties)

You've misunderstood. Once you have properties it makes sense to go a certain way. If you don't, it makes more sense to add records and not properties.

Now you don't have to agree with the Java team's decisions. Programmers rarely agree on much. But I think you should at least appreciate the irony that if we had added properties, I would be responding right now to another equally annoyed person complaining that we're not learning the lessons of Go and Zig and Rust, which have refused to add properties, and couldn't we see what an obviously stupid idea it was.

Re: Making Lenses Practical in Java

#79
post #78

Earlier quoted context omitted.

> and there needs to be a good reason for that. A year ago I already said all the good reasons. There are many reasons why things like Lombock exist. There are reasons why people loathe writing interminable chains of builder methods. But sure. None of these are good reasons because something something Visual Basic. What Java will inevitably end up with is a yet another half-assed approach that only exists for a small…

> The C# approach was sensible for them because they could build on features they already had (default parameters, properties) You've misunderstood. Once you have properties it makes sense to go a certain way. If you don't, it makes more sense to add records and not properties. Now you don't have to agree with the Java team's decisions. Programmers rarely agree on much. But I think you should at least appreciate the…

> But I think you should at least appreciate the irony that if we had added properties, I would be responding right now to another equally annoyed person complaining that we're not learning the lessons of Go and Zig and Rust

Most likely not.

Meanwhile C# could build on the strength of what they have in the language. And Java, and I cannot repeat it enough times, will have a half-assed solution applicable only to a small part of the language while keeping the inanity of manual `.of` methods, manual interminable chains of builder methods, and other half-assed solutions everywhere else.

While denigrating other languages and their decisions.

Even the link you provided clearly states this: "And, everything we can do with records but not with classes increases a gap where users might feel they have to make a hard choice; it's time to start charting the path of generalizing the record "goodies" so that suitable classes can join in the fun."

Again: while others have built on the languages features they have, and they are immediately propagated through the language with little to no additional effort, "Java does not adopt strategies from less successful products", and "keep the language conservative". And yet here we are, "learning from C#" and struggling how to figure out a simple (for some definition of simple) addition so that it works with the rest of the language that has languished in the "conservative" land for too long.

Edit.

I also wonder how many of the things that are currently placeholders will be required and will surpass anything C# and other "lesser languages" have come up with: factory, __byname, __deconstructor etc.

Re: Making Lenses Practical in Java

#80
post #34

Earlier quoted context omitted.

In the works: https://github.com/openjdk/amber-docs/blob/master/eg-drafts/...

I hope they will find a better solution, as this proposal will break encapsulation. Let’s say you model allowed transitions via business methods and thus restrict certain state changes. You can either serialize or deserialize state or perform an allowed transition. If wither becomes a language feature, it will allow forbidden state changes that cannot be caught by validation in constructor, which will allow deseriali…

I don’t believe this is true. From my reading of the document, all with expressions go through the primary constructor.
Post reply on HN