Hi Viktor, thanks again for sharing your design decisions. I agree this is a 
minor matter because not many programmers will implement gatherers. Let me try 
to explain my confusion.

On 15/10/2024 13:46, Viktor Klang wrote:

Making of() the short-name is because it is more capable than ofGreedy() (which 
does not support short-circuiting). So using it signals a choice of less 
capability.

I don't understand why a short-circuiting integrator is "more capable" than a greedy one. 
And why the "less capable" one would then be the subclass.

What is the capability? To never short-circuit? To signal short-circuiting?

The reason for ofSequential/of instead of ofParallel/of is that a 
parallel-capable Gatherer covers more scenarios than a sequential-only 
versison, so giving the shorter name to the less-capable version would not 
stand out in the same way when reviewing, and Collector.of is parallel-capable, 
which seemed more consistent to make Gatherer.of parallel-capable as well.

Again, what is "less capable"?

When you write "not stand out in the reviewing", I interpret that as follows: "of" means 
the mechanism providing maximum efficiency, that we want implementors to use. And "ofXXX" means 
they didn't go all the way, either because of the nature of the processing or because they didn't take the 
trouble to do all the work.

With of/ofSequential, I can see that point of view. "ofSequential" is a warning 
that, when used with a parallel stream, there is the potential for disappointment.

But what about implementing a gatherer that never short-circuits, like all three 
gatherers in the JEP? Here, "ofGreedy" is an indication that an optimization 
can be made (pushing vs. pulling), right? And that's what we want the implementor to 
choose.

That's where my struggle comes in. How can I phrase my advice in a symmetric way? Right now, my 
advice is "if the integrator doesn't short-circuit, advertise that benefit by using 
ofGreedy" and "if the gatherer can't combine results, advertise that drawback by using 
ofSequential".

Or maybe I misunderstand greedy?


 >First off, I think factory methods should be the favored approach.

Is there something which could be made clearer around that, because that's how 
I already view it.

Put the factory method first in the JEP :-)

 >The details are fussy, with the marker interface and the magic default 
combiner.

I think this is worth expanding a bit on, in what way are they fussy?


Maybe fussy is not a good term. Baroque? This is what went through my head when 
I studied the design.

1. The way to tell whether a gatherer is sequential is very unusual. To provide 
a sequential gatherer I must fail to override a default method. I don't recall 
seeing anything like this in the Java API.

2. The way to tell whether an integrator is greedy is through a subinterface. 
That's fine, except it's a marker interface with no new methods. And then why 
not use a subinterface for parallelizable gatherers, where one could make 
combiner a subinterface method? Too OO for 2024?

3. Here we have two different mechanisms for what streams and collectors 
address with a simple and unified approach: flags.

I don't strongly care about this, just answering your question.

Cheers,

Cay

--

Cay S. Horstmann | https://horstmann.com

Reply via email to