explode()
Kevin Bourrillion
kevinb at google.com
Tue Jan 29 10:01:03 PST 2013
Hmm. So the methods I proposed, Consumer.accept(Collection) and
Consumer.accept(Stream), are functionally identical to
Collection.forEach(consumer) and Stream.forEach(consumer), and thus have
little benefit except in that various Consumer implementations might be
able to override them and do something more efficient. Which in turn means
that these forEach() methods would have to delegate straight to them; they
become pure conveniences only.
So, I guess either we can imagine enough use cases of a consumer that wants
to optimize these, to make the whole idea seem worthwhile, or we can't, and
we can just drop it.
But when considering those use cases, one of them may arise if drop
Downstream and have explode() use Consumer instead. In that case, does it
break explode() if we have users just using stream.forEach(consumer)
and collection.forEach(consumer) instead of downstream.send(stream) and
downstream.send(collection)?
On Thu, Jan 24, 2013 at 2:43 PM, Kevin Bourrillion <kevinb at google.com>wrote:
> explode() is aptly named for what it did to my brain when I encountered
> it. :-)
>
> A few things are adding up to make it impenetrable.
>
> 1. The vast majority of the Stream API, save the obvious exceptions like
> forEach(), is solidly in the functional style. Collectors aren't really,
> but as long as I use the prepackaged ones, it *feels* fairly functional
> anyway. Now suddenly there's explode, which doesn't feel functional at all.
> Instead, I need to think of the bit of code I provide to it as an active
> participant in a pipeline. Things are fed to me, I feed things on down the
> line. This makes it different, and different is automatically confusing.
> This can't really be *corrected*, but seems worth nothing; maybe we can
> account for the difference somehow.
>
> 2. In attempting to learn it, I'm confronted with a type,
> Stream.Downstream<U>, which I won't have heard of before that moment, and
> whose name reveals little. Is there any particular reason that
> Sink/Consumer, with its accept(T) method, should not also have "default"
> methods implementing accept(Collection<T>) and accept(Stream<T>) and
> accept(T[])? I can't think of any; those sound just plain handy. And if
> we added those, would there be enough value in preserving Downstream as an
> identically-signatured type? We could dispense with it, as I've done below.
>
> 3. Except sometimes there *is* value in having a special type even if its
> signature is identical to another. I suspect that a custom type could help
> quite a bit in this case:
>
> interface Exploder<T,R> {
> /**
> * Maps {code input} to zero or more instances of R, sending these
> * to {@code resultConsumer} to be included in the results of
> * {@link Stream#explode(Exploder)}.
> */
> void explode(T input, Consumer<R> resultConsumer);
> }
>
>
> 4. Then there is the name "explode". It's... okay. "unpack"? Nah. It seems
> maybe 40% possible that a great name is out there eluding us....
>
>
>
> --
> Kevin Bourrillion | Java Librarian | Google, Inc. | kevinb at google.com
>
--
Kevin Bourrillion | Java Librarian | Google, Inc. | kevinb at google.com
More information about the lambda-libs-spec-observers
mailing list