----- Original Message -----
> From: "Tagir Valeev" <[email protected]>
> To: "Remi Forax" <[email protected]>
> Cc: "core-libs-dev" <[email protected]>
> Sent: Monday, May 23, 2022 8:01:44 AM
> Subject: Re: <T> Stream.fromForEach(Consumer<Consumer<T>>)
> Hello!
>
> There's a Stream.builder for this purpose:
>
> var builder = Stream.<String>builder();
> new Parser("1 2 3").parse(builder);
> builder.build().forEach(System.out::println);
>
> A little bit more verbose than your suggestion but this way it's more
> clear that the whole stream content will be buffered.
I should have mentioned the Stream.builder, as you said, the Stream.Builder
stores the whole elements in memory before creating the stream,
it's equivalent to storing the elements in a List and calling List.stream.
Stream.fromForEach like stream.mapMulti() does not stores the elements.
(technically, stream.mapMulti() stores the elements if the default method
implementation is used but this implementation is only used if you write your
own Stream, the JDK implementation does not store the elements)
>
> With best regards,
> Tagir Valeev
regards,
Rémi
>
> On Sun, May 22, 2022 at 5:54 AM Remi Forax <[email protected]> wrote:
>>
>> Hi all,
>> a stream is kind of push iterator so it can be created from any object that
>> has
>> a method like forEach(Consumer),
>> but sadly there is no static method to create a Stream from a Consumer of
>> Consumer so people usually miss that creating a Stream from events pushed to
>> a
>> consumer is easy.
>>
>> By example, let say i've a very simple parser like this, it calls the
>> listener/callback for each tokens
>>
>> record Parser(String text) {
>> void parse(Consumer<? super String> listener) {
>> for(var token: text.split(" ")) {
>> listener.accept(token);
>> }
>> }
>> }
>>
>> Using the method Stream.fromForEach, we can create a Stream from the
>> sequence of
>> tokens that are pushed through the listener
>> var parser = new Parser("1 2");
>> var stream = Stream.fromForEach(parser::parse);
>>
>> It can also works with an iterable, an optional or even a collection
>> Iterable<String> iterable = ...
>> var stream = Stream.fromForEach(iterable::forEachRemaning);
>>
>> Optional<String> optional = ...
>> var stream = Stream.fromForEach(optional::ifPresent);
>>
>> List<String> list = ...
>> var stream = Stream.fromForEach(list::forEach);
>>
>> I known the last two examples already have their own method stream(), it's
>> just
>> to explain how Stream.fromForEach is supposed to work.
>>
>> In term of implementation, Stream.fromForEach() is equivalent to creating a
>> stream using a mapMulti(), so it can be implemented like this
>>
>> static <T> Stream<T> fromForEach(Consumer<? super Consumer<T>> forEach) {
>> return Stream.of((T) null).mapMulti((__, consumer) ->
>> forEach.accept(consumer));
>> }
>>
>> but i think that Stream.fromForEach(iterable::forEachRemaning) is more
>> readable
>> than Stream.of(iterable).mapMult(Iterable::forEachRemaining).
>>
>> The name fromForEach is not great and i'm sure someone will come with a
>> better
>> one.
>>
>> regards,
> > Rémi