Fw: New candidate JEP: 485: Stream Gatherers
Cay Horstmann
cay.horstmann at gmail.com
Tue Oct 15 14:07:50 UTC 2024
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
More information about the core-libs-dev
mailing list