<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<style type="text/css" style="display:none;"> P {margin-top:0;margin-bottom:0;} </style>
</head>
<body dir="ltr">
<br>
<div>
<div style="font-family: arial, helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<div data-marker="__QUOTED_TEXT__">
<blockquote style="border-left: 2px solid rgb(16, 16, 255); margin-left: 5px; padding-left: 5px; font-weight: normal; font-style: normal; text-decoration: none; font-family: Helvetica, Arial, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<div>
<div style="font-family: arial, helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<div class="x_elementToProof">
<blockquote style="border-left: 2px solid rgb(16, 16, 255); margin-left: 5px; padding-left: 5px; font-weight: normal; font-style: normal; text-decoration: none; font-family: Helvetica, Arial, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<div class="x_x_elementToProof" style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div class="x_x_elementToProof" style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
Over the past 6+ months I've been thinking about, and tinkering with, how we'd be able to expose a user-facing API for extensible intermediate java.util.stream.Stream operations¡ªa feature envisioned all the way back when Streams were created.<br>
</div>
<div class="x_x_elementToProof" style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div class="x_x_elementToProof" style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
I'm now at a point where I have a viable design and implementation, and so I'm turning to you for your feedback: on the direction taken; the API concepts; and, in particular, is there anything which I have overlooked/missed?</div>
</blockquote>
<div><br>
</div>
<div class="x_elementToProof">>I think this API is overly generic and hard to reason about it, for users and IDEs.
<br>
</div>
<div class="x_elementToProof"><br>
</div>
<div class="x_elementToProof">The API is for all intents and purposes Collector with a boolean return type for the accumulator and an added downstream handle parameter added to the accumulator and the finisher.<br>
</div>
<div><br>
</div>
<div class="x_elementToProof">>The main issue is that the same API is used for both stateless and stateful operations, which means that as a user, we have no idea if a call to stream.gather() is stateful or not.
<br>
</div>
<div class="x_elementToProof"><br>
</div>
<div class="x_elementToProof">How is this different from any of the other pre-existing Stream operations?</div>
</div>
</div>
</div>
</blockquote>
<div><br>
</div>
<blockquote style="border-color: rgb(200, 200, 200); border-left: 3px solid rgb(200, 200, 200); padding-left: 1ex; margin-left: 0.8ex;" itemscope="" itemtype="https://schemas.microsoft.com/QuotedText">
<div>Most of the operation are stateless, only a handful of well known operations are stateful, all other stateful operations are done by collectors.<br data-mce-bogus="1">
</div>
<div>But stream.gather() allows both stateless and stateful gatherer.<br data-mce-bogus="1">
</div>
<div>I believe that instead of having an intermediary operation that can be stateless or stateful, it's better to have a Collector that starts a new stream.<br data-mce-bogus="1">
</div>
<div><br data-mce-bogus="1">
</div>
<div>Instead of<br data-mce-bogus="1">
</div>
<div>  stream.gather(Gatherers.foo())<br data-mce-bogus="1">
</div>
<div><br data-mce-bogus="1">
</div>
<div>A collector/gatherer can propagate the elements into a new stream<br data-mce-bogus="1">
</div>
<div>  stream.collect(Gatherers.foo(stream -> ...))<br data-mce-bogus="1">
</div>
<div> or<br data-mce-bogus="1">
</div>
<div>  stream.collect(Gatherers.foo(), stream -> ...)<br data-mce-bogus="1">
</div>
<div><br data-mce-bogus="1">
</div>
<div>This allows a better control on the parallelization (both streams are independant) and a clear path to retrofit the Collectors as Gatherers (instead of having two too similar APIs side by side).<br data-mce-bogus="1">
</div>
</blockquote>
<div class="elementToProof"><br>
</div>
<div class="elementToProof">There is no difference in how parallelization would be possible to occur¡ªparallel Stream already runs multi-stage parallel evaluation when stateful stages exist in the same pipeline.<br>
</div>
<div class="elementToProof"><br data-mce-bogus="1">
</div>
<blockquote style="border-left: 2px solid rgb(16, 16, 255); margin-left: 5px; padding-left: 5px; font-weight: normal; font-style: normal; text-decoration: none; font-family: Helvetica, Arial, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<div>
<div style="font-family: arial, helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<div class="x_elementToProof">
<div class="x_elementToProof"><br>
</div>
<div class="x_elementToProof"><br>
</div>
<div class="x_elementToProof">>Which is a departure from the current API that cleanly separate stateless and staful operations. Here, we are left in the dark. In a sense, this API is too powerful, it can do too much thing, so as a user we can not reason about
 it.</div>
<div class="x_elementToProof"><br>
</div>
<div class="x_elementToProof">A Gatherer encodes it input and output types, in what sense would that not be enough to reason about it ?</div>
</div>
</div>
</div>
</blockquote>
<div><br>
</div>
<blockquote style="border-color: rgb(200, 200, 200); border-left: 3px solid rgb(200, 200, 200); padding-left: 1ex; margin-left: 0.8ex;" itemscope="" itemtype="https://schemas.microsoft.com/QuotedText">
<div>The initial idea of the API is to have almost all intermediary operations to be stateless so by default, we know that the complexity of the stream is linear,  it will parallelize quite well, etc.<br data-mce-bogus="1">
</div>
<div>Once you have an intermediary operation like a gatherer, all this "good" property are null and void.<br data-mce-bogus="1">
</div>
</blockquote>
<div class="elementToProof"><br>
</div>
<div class="elementToProof">There are quite a few stateful operations on streams since a long time¡ªthe slicing operations, the distinct operations, the sorting operations, the limit operation, the while-operations etc. My bet is that most developers using streams
 will not know from a glance which ones of those are to be considered stateful and has an impact on evaluation¡ªand personally I think that is a great thing, as it is an implementation detail.<br>
</div>
<div class="elementToProof"><br data-mce-bogus="1">
</div>
<blockquote style="border-left: 2px solid rgb(16, 16, 255); margin-left: 5px; padding-left: 5px; font-weight: normal; font-style: normal; text-decoration: none; font-family: Helvetica, Arial, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<div>
<div style="font-family: arial, helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<div class="x_elementToProof">
<div class="x_elementToProof"><br>
</div>
<div><br>
</div>
<div class="x_elementToProof">>I like the idea of a Collector 2.0 i.e. using the Gatherer API at the end of the stream (not in the middle), but currently, the Gatherer API is not a Collector, so we now have two different APIs for doing partially the same job.
 I wonder if the Collector API can be retroffitted to act as a Gatherer API, avoiding to have to choose which one to use, a gatherer being the equivalent of a "flat-collector" + short-circuit.</div>
<div class="x_elementToProof"><br>
</div>
<div class="x_elementToProof">Collector serves a very important role of being able to get information
<b>out of</b> a Stream and deliver that information in a certain shape, a Gatherer does not provide any facility for this.</div>
</div>
</div>
</div>
</blockquote>
<blockquote style="border-color: rgb(200, 200, 200); border-left: 3px solid rgb(200, 200, 200); padding-left: 1ex; margin-left: 0.8ex;" itemscope="" itemtype="https://schemas.microsoft.com/QuotedText">
<div class="">A collector can get information out of a Stream <strong>into a new one</strong>, at that point you have something quite similar to a Gatherer.<br data-mce-bogus="1">
</div>
</blockquote>
<div class="elementToProof">It sounds like you're describing Gatherer¡ªit's a Collector like construct which can output into a new stream.<br data-mce-bogus="1">
</div>
<blockquote style="border-left: 2px solid rgb(16, 16, 255); margin-left: 5px; padding-left: 5px; font-weight: normal; font-style: normal; text-decoration: none; font-family: Helvetica, Arial, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<div>
<div style="font-family: arial, helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<div class="x_elementToProof">
<div class="x_elementToProof"><br>
</div>
<div class="x_elementToProof"><br>
</div>
>The idea of unsupportedCombiner() seems out of place, like a patch to be able to clobble different things together. I'm not sure to understand why it's needed for a Gatherer, and why it is not needed for Collectors ?<br>
<div class="x_elementToProof"><br>
</div>
<div class="x_elementToProof">Nothing prevents us from treating a `null` combiner the same way. My primary reason for making it a dedicated thing was to be able to differentiate a possible bug (user passing in a null reference inadvertently) from explicitly
 stating that a combiner does not exist from this operation.</div>
<div class="x_elementToProof"><br>
</div>
<div class="x_elementToProof"><i>unsupportedCombiner()</i> as an artifact can be completely hidden if desired, as
<i>Gatherer.of()</i> can have permutations without specifying a combiner, and the
<i>default method</i> of Gatherer.combiner() could return <i>unsupportedCombiner()</i>. I opted not to do this initially, because I felt like being explicit about not having a combiner means that it is a concious decision by the implementor of the Gatherer.</div>
</div>
</div>
</div>
</blockquote>
<blockquote style="border-color: rgb(200, 200, 200); border-left: 3px solid rgb(200, 200, 200); padding-left: 1ex; margin-left: 0.8ex;" itemscope="" itemtype="https://schemas.microsoft.com/QuotedText">
<div class="">My question is more, why do we need this unsupportedCombiner on a Gatherer and not on a Collector ?<br data-mce-bogus="1">
</div>
</blockquote>
<div class="elementToProof">We can definitely investigate adding that to Collector as well, but it is outside of the scope of this proposal as it deals with intermediate, not terminal, operations.<br data-mce-bogus="1">
</div>
<blockquote style="border-left: 2px solid rgb(16, 16, 255); margin-left: 5px; padding-left: 5px; font-weight: normal; font-style: normal; text-decoration: none; font-family: Helvetica, Arial, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<div>
<div style="font-family: arial, helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<div class="x_elementToProof">
<div class="x_elementToProof"><br>
</div>
<div class="x_elementToProof"><br>
</div>
<div class="x_elementToProof"><br>
</div>
<div class="x_elementToProof">>So I would prefer that API to extends the current Collector API but not the intermediary operations. Yes, it's less powerful.<br>
</div>
<div class="x_elementToProof">It means that instead of using one stream with a collect like operation in the middle, users will have to use two streams, one after the other, but it makes the code easier to understand (also having two streams give users better
 control on which part should be in parallel).</div>
<div class="x_elementToProof"><br>
</div>
<div class="x_elementToProof">That would be something completely different from the goal of providing user-extensible intermediate operations, which is something which this proposal is explicitly trying to address.</div>
</div>
</div>
</div>
</blockquote>
<blockquote style="border-color: rgb(200, 200, 200); border-left: 3px solid rgb(200, 200, 200); padding-left: 1ex; margin-left: 0.8ex;" itemscope="" itemtype="https://schemas.microsoft.com/QuotedText">
<div class="">User-extensible intermediate operations or a gatherer as a better collector have similar semantics, so it's not a completely different.<br>
</div>
</blockquote>
<div class="elementToProof">The difference in semantics between Gatherer and Collector is outlined in the initial post of this document. With that said, I think your position has been made clear¡ªyou prefer augmenting the terminal operation rather than introducing
 an intermediate operation.<br data-mce-bogus="1">
</div>
<blockquote style="border-left: 2px solid rgb(16, 16, 255); margin-left: 5px; padding-left: 5px; font-weight: normal; font-style: normal; text-decoration: none; font-family: Helvetica, Arial, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<div>
<div style="font-family: arial, helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<div class="x_elementToProof">
<div class="x_elementToProof"><br>
</div>
<div class="x_elementToProof">Cheers,</div>
<div class="x_elementToProof">¡Ì<br>
</div>
</div>
</div>
</div>
</blockquote>
<div><br>
</div>
<div>regards,<br data-mce-bogus="1">
</div>
<div>R¨¦mi<br data-mce-bogus="1">
</div>
<div><br data-mce-bogus="1">
</div>
<blockquote style="border-left: 2px solid rgb(16, 16, 255); margin-left: 5px; padding-left: 5px; font-weight: normal; font-style: normal; text-decoration: none; font-family: Helvetica, Arial, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<div>
<div style="font-family: arial, helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<div class="x_elementToProof">
<div class="x_elementToProof"></div>
<div class="x_elementToProof">>R¨¦mi<br>
</div>
<div><br>
</div>
<blockquote style="border-left: 2px solid rgb(16, 16, 255); margin-left: 5px; padding-left: 5px; font-weight: normal; font-style: normal; text-decoration: none; font-family: Helvetica, Arial, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<div class="x_x_elementToProof x_x_ContentPasted0" style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<div class="x_x_ContentPasted0 x_x_elementToProof"><br>
</div>
<div class="x_x_ContentPasted0 x_x_elementToProof">(If you, like myself, prefer reading pre-rendered markdown,
<a href="https://cr.openjdk.org/~vklang/Gatherers.html" data-auth="NotApplicable" title="https://cr.openjdk.org/~vklang/Gatherers.html" id="LPlnk689721" data-loopstyle="linkonly">
click here</a>)<br>
</div>
</div>
<div><br>
</div>
<div><br>
</div>
</blockquote>
</div>
</div>
</div>
<br>
</blockquote>
</div>
</div>
</div>
</body>
</html>