Live data from Hacker News

Making Lenses Practical in Java

chriskiehl.com

31–40 of 108 posts

Re: Making Lenses Practical in Java

#31

Earlier quoted context omitted.

You do not need lenses for implementation of a method working with internal state, that will be a gross over-engineering. record Order(List approvals, int version, OrderStatus status) { Order confirmed(Instant timestamp, UUID approver) { var approvals = this.approvals.stream().map(a-> a.user().uuid().equals(approver) ? a.confirmed(timestamp) : a).toList(); return new Order(approvals, version++, OrderStatus.APPROVED);…

Lenses are an abstraction of what you mentioned. For a single example it's of course overengineering. The benefit is that e.g. when you have a bunch of methods like that, you can avoid duplicating the code that is responsible for copying the inner layers. Otherwise if you e.g. add a layer, you have to touch all those methods.

If you look at my example you will notice that it has zero lines that would be duplicated in real life scenarios, because it does not perform a deep copy (a benefit of using immutable objects).

Re: Making Lenses Practical in Java

#32
post #26
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…

The real power IMHO comes once you start using traversals, which are like lenses but focus 0..n elements instead of exactly 1, and compose well with themselves and with lenses. (It gets better still after that, as you add in Folds, Isos, Prisms, etc., but we'll leave those for now) Once you have a traversal that can pull out immediate children of the same type (e.g., "given a DOM node, traverse all of its children"),…

> (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 effort-saving worthwhile?

Re: Making Lenses Practical in Java

#33

Earlier quoted context omitted.

Record classes arguably do a lot of the same thing without the drawbacks.

But they require a new JDK version, and a surprisingly high amount of Java projects are still stuck on JDK8.

JDK 8 is now a minority, and if we count only projects that are still undergoing significant development it's a significantly smaller minority. The main reason some projects are still stuck on 8 is because they use old libraries that have made breaking changes, and don't have resources to adapt their use, let alone take on new ones.

Re: Making Lenses Practical in Java

#34

Earlier quoted context omitted.

Record classes arguably do a lot of the same thing without the drawbacks.

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

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

Re: Making Lenses Practical in Java

#35
post #9

I don't agree on the fact that lombok has brought us out of the dark ages. We used to use it, but it has some drawbacks. One of them, it's an additional dependency. This, for a simple thing such as pojo, seems a bit overkill to me. The additional amount of time used to write some cose isn't worth the risk of additional bugs hidden in having one more dependency.

Lombok is a compiler extension, not a dependency. It does actually need to be present at runtime!

Re: Making Lenses Practical in Java

#36
The library (if I read correctly) seems to lack traversals, so no "each". Is it true that if I nest collections I am still in deep pain?

Nonetheless still a cool library. The APIs in many cases look surprisingly natural.

Re: Making Lenses Practical in Java

#37
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/...

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 deserialization of states A, B, C, but will not know that A->C is forbidden, thus making the following possible:

   var r = new R(A);
   r = r with { state = C; } // passes, resulting in untraceable error much later
where alternative could be:

   r = r.transitionTo(C); // throws exception

Re: Making Lenses Practical in Java

#38
post #9

I don't agree on the fact that lombok has brought us out of the dark ages. We used to use it, but it has some drawbacks. One of them, it's an additional dependency. This, for a simple thing such as pojo, seems a bit overkill to me. The additional amount of time used to write some cose isn't worth the risk of additional bugs hidden in having one more dependency.

Lombok is a compiler extension, not a dependency. It does actually need to be present at runtime!

Does not? But you could still see it as a transitive dependency of sorts.

Re: Making Lenses Practical in Java

#39
post #9

I don't agree on the fact that lombok has brought us out of the dark ages. We used to use it, but it has some drawbacks. One of them, it's an additional dependency. This, for a simple thing such as pojo, seems a bit overkill to me. The additional amount of time used to write some cose isn't worth the risk of additional bugs hidden in having one more dependency.

Lombok is a compiler extension, not a dependency. It does actually need to be present at runtime!

It's a compile-time dependency.

Re: Making Lenses Practical in Java

#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.
Post reply on HN