Loose end: concat

Brian Goetz brian.goetz at oracle.com
Tue May 28 11:19:17 PDT 2013


So, for the record, the instance version is really "false fluency". 
Consider:

   list.filter(...)
       .map(...)
       .concat(otherList.filter(....)
                        .map(....)
                        .distinct()
                        .sorted())
       .forEach(...);

is not really very fluent either -- the argument to concat is likely to 
be quite a mouthful.  If you separate out:

Stream other = otherList.filter(....)
                        .map(....)
                        .distinct()
                        .sorted())
   list.filter(...)
       .map(...)
       .concat(other)
       .forEach(...);

now you've lost half your "fluency" by having to have a backward ref to 
other anyway.  Making:

Stream a = otherList.filter(....)
                        .map(....)
                        .distinct()
                        .sorted())
Stream b = list.filter(...)
       .map(...);
concat(a, b).forEach(...)

not all that much worse.

But that simply undermines the (only) "pro" for making it an instance 
method.  The real reason is that the "con" is overwhelming: all other 
stream transforms are pure functions, whereas concat() is irretrievably 
stateful.  This means that it becomes impossible to build functional 
layers atop streams.  Given that the only benefit of the instance route 
is fluency, and it isn't really very fluent anyway, the answer seems 
obvious?

On 5/28/2013 12:44 PM, Joe Bowbeer wrote:
> I like the second, still, for its fluency. I didn't understand your
> stateful-based argument. Are you backing away from it?
>
> On May 28, 2013 9:35 AM, "Brian Goetz" <brian.goetz at oracle.com
> <mailto:brian.goetz at oracle.com>> wrote:
>
>     Seems we've seen no objections on the existence of these methods.
>       So the remaining issue is where they live.
>
>     Candidates:
>
>        Streams.concat(a, b) x 4
>        Stream.concat(a, b), IntStream.concat(a, b), etc.
>
>     Over time, we've been moving away from "overloaded" stream methods
>     towards more explicitly typed methods, which is a point against the
>     first candidate.
>
>     I initially preferred the first version, but am more on the fence
>     now. Sam prefers the second.  Other opinions?
>
>
>     On 5/23/2013 2:06 PM, Brian Goetz wrote:
>
>         I cleaned up concat() and wrote Int/Long/Double versions.
>           (Fortunately,
>         with the recent addition of Spliterator.OfPrimitive, the duplication
>         quotient was much lower.)
>
>         Currently these still live in Streams.  Is that still the right
>         place?
>         The stream classes (Stream, IntStream, etc) seem a little wrong for
>         them, but I can't quite put my finger on why.
>
>         Specs:
>
>               /**
>                * Creates a lazy concatenated {@code Stream} whose
>         elements are
>         all the
>                * elements of a first {@code Stream} succeeded by all the
>         elements
>         of the
>                * second {@code Stream}. The resulting stream is ordered
>         if both
>                * of the input streams are ordered, and parallel if
>         either of the
>         input
>                * streams is parallel.
>                *
>                * @param <T> The type of stream elements
>                * @param a the first stream
>                * @param b the second stream to concatenate on to end of
>         the first
>                *        stream
>                * @return the concatenation of the two input streams
>                */
>               public static <T> Stream<T> concat(Stream<? extends T> a,
>         Stream<?
>         extends T> b) {
>
>
>               /**
>                * Creates a lazy concatenated {@code IntStream} whose
>         elements are
>         all the
>                * elements of a first {@code IntStream} succeeded by all the
>         elements of the
>                * second {@code IntStream}. The resulting stream is
>         ordered if both
>                * of the input streams are ordered, and parallel if
>         either of the
>         input
>                * streams is parallel.
>                *
>                * @param a the first stream
>                * @param b the second stream to concatenate on to end of
>         the first
>         stream
>                * @return the concatenation of the two streams
>                */
>               public static IntStream concat(IntStream a, IntStream b) {
>
>
>         (and similar for Long and Double).
>


More information about the lambda-libs-spec-observers mailing list