Hi Anthony, Thanks for your suggestion of using a Stream.Builder instead of a Consumer. However, one of the goals for mapMulti is not to create an additional Stream. Also, I fear that using a builder, but throwing an exception on a call to build, is counter-intuitive and perhaps confusing to the user.
Kind regards, Patrick > On 25 Jun 2020, at 18:12, Anthony Vanelverdinghe <d...@anthonyv.be> wrote: > > Hi > > Given the signature of flatMap is: > <R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> > mapper) > > I'd like to propose the following signature for the new method: > <R> Stream<R> builderMap(BiConsumer<? super T, ? super Stream.Builder<R>> > mapper) > > This way both methods are named "...Map", and the name "builderMap" follows > naturally from the argument's type. > If the given mapper invokes Stream.Builder::build, an IllegalStateException > should be thrown. > > Kind regards, > Anthony > > On 25/06/2020 02:58, Paul Sandoz wrote: >> Hi, >> >> We traded CPS style for reusing existing functional interfaces. Originally >> the signature (my first choice) was as you indicate. >> >> By chance it just so happens that the current signature is the same shape as >> that for the accumulating argument type of the three arg collect terminal >> operation: >> >> Stream >> <R> R collect(Supplier<R> supplier, >> BiConsumer<R, ? super T> accumulator, >> BiConsumer<R, R> combiner); >> >> IntStream >> <R> R collect(Supplier<R> supplier, >> ObjIntConsumer<R> accumulator, >> BiConsumer<R, R> combiner); >> >> Same for the accumulator of a Collector too. >> >> However, I suspect you would argue these terminal accumulation cases are >> different from the intermediate case, as we are not accumulating but passing >> or accepting (loosely returning) zero or more elements that replace the >> input element. >> >> It’s my hope that generic specialization will allow the primitive stream >> types to fade into the background, along with the primitive functional >> interfaces. In that respect the addition of three functional interfaces for >> use on the primitive stream types is not so terrible. >> >> >> Regarding the name, you should have seen the first one :-) it was terrible. >> >> Here’s my few brush strokes on the bike shed. I wonder what people think of >> mapAccept. The specification talks about accepting elements, because that is >> the operative method name on Consumer. So we can say "T is replaced with the >> elements accepted by the Consumer<R>", or “ The Consumer<R> accepts the >> elements that replace T" >> >> Paul. >> >> >> >>> On Jun 24, 2020, at 1:01 PM, John Rose <john.r.r...@oracle.com> wrote: >>> >>> I like this new API point a lot; it allows flexible, local, temporary >>> control inversion in the context of one stream transform. >>> >>> What’s the performance model? It seems like the SpinedBuffer >>> implementation makes a worst-case assumption about the number >>> of pending values, that there will be many instead of zero or one. >>> >>> But I guess the pipeline stuff already works in terms of pushes, so >>> the good news might be that this is really just a drill-down from the >>> user API into the kinds of operations (push-flavored) that go on >>> most of the time. >>> >>> OK, so I like the function but I have a beef with its bike shed >>> color. First of all, this is a control-inversion (CPS) pattern, >>> which is very powerful but also notoriously hard to read. >>> I think that in Java APIs, at least in Stream APIs, code is >>> easier to read if the logical data flow is from left to right. >>> >>> (This is a language-specific observation. Apart from varargs, >>> Java method APIs read favorably when extra control arguments >>> are added onto the end of the argument list. Also, the convention >>> for generic functional interfaces is that the return value type >>> goes to the right, e.g., R in Function<A,R>.) >>> >>> So the BiConsumer is backwards, because the logical return >>> should be written, if not as a true return (which would appear >>> at the end of type parameter lists), at the end of the incoming >>> parameters (and in the last type parameter). >>> >>> I also think “multi” is needlessly “learned” sounding. A simple >>> spatial preposition would work well: mapThrough, mapAcross, etc. >>> I think I prefer mapAcross because the term “across” can be read >>> adverbially: “we are mapping T across to Consumer<R>”. >>> >>> So: >>> >>> mapAcross(BiConsumer<? super T, Consumer<R>> mapper) >>> mapAcrossToInt(BiConsumer<? super T, IntConsumer> mapper) >>> mapAcross(IntObjConsumer<IntConsumer> mapper) >>> >>> This does require additional FI’s like IntObjConsumer, but >>> I think that is a negligible cost. Making the control inversion >>> *readable* is the high order bit here, not minimizing the number >>> of trivial FIs. >>> >>> (I almost hear David Bowman, in his space suit, saying, “My API… >>> It’s full of bikesheds!” There’s a meme for that.) >>> >>> — John >>> >>> On Jun 24, 2020, at 3:57 AM, Patrick Concannon >>> <patrick.concan...@oracle.com> wrote: >>>> Hi, >>>> >>>> Could someone please review myself and Julia's RFE and CSR for JDK-8238286 >>>> - 'Add new flatMap stream operation that is more amenable to pushing’? >>>> >>>> This proposal is to add a new flatMap-like operation: >>>> >>>> `<R> Stream<R> mapMulti(BiConsumer<Consumer<R>, ? super T> mapper)` >>>> >>>> to the java.util.Stream class. This operation is more receptive to the >>>> pushing or yielding of values than the current implementation that >>>> internally assembles values (if any) into one or more streams. This >>>> addition includes the primitive variations of the operation i.e. >>>> mapMultiToInt, IntStream mapMulti, etc. >>>> >>>> issue: https://bugs.openjdk.java.net/browse/JDK-8238286 >>>> <https://bugs.openjdk.java.net/browse/JDK-8238286> >>>> csr: https://bugs.openjdk.java.net/browse/JDK-8248166 >>>> <https://bugs.openjdk.java.net/browse/JDK-8248166> >>>> >>>> webrev: http://cr.openjdk.java.net/~pconcannon/8238286/webrevs/webrev.00/ >>>> <http://cr.openjdk.java.net/~pconcannon/8238286/webrevs/webrev.00/> >>>> specdiff: >>>> http://cr.openjdk.java.net/~pconcannon/8238286/specdiff/specout.00/overview-summary.html >>>> >>>> <http://cr.openjdk.java.net/~pconcannon/8238286/specdiff/specout.00/overview-summary.html> >>>> >>>> >>>> Kind regards, >>>> Patrick & Julia