Q on Patterns and Streams

Johannes Kuhn info at j-kuhn.de
Wed Jan 20 15:23:30 UTC 2021


Thanks for the reply.

Stream.mapMulty does indeed help a bit.
I think your examples need a type hint so they would actually compile - 
.<P>mapMulti(...).

If I had to guess the future, then I would guess that a pattern, 
followed by the creation of some product type (record...) could be often 
desired. But that's just a guess.

Sure, this can be expressed with .mapMaybe(pattern ? Optional.of(new 
Result(a, b, c)) : Optional.empty()).

But you have it on your radar, so I am certain that you will come up 
with something better.

- Johannes

PS.: Java's type inference is complicated, and limited compared to 
haskell. I still don't understand why one of the following lines doesn't 
compile:

    Supplier<Iterator<? extends CharSequence>> s = () -> 
List.of("foo").iterator();
    Iterable<? extends CharSequence> i = () -> List.of("Foo").iterator();

To me, they appear to have the same shape. Type inference is 
complicated. Or I don't have the right mental model for it.

On 20-Jan-21 15:54, Brian Goetz wrote:
> Indeed, this is a question we've wrestled with.
> 
> You are right that this is a sort of flatMap.  And that the current 
> flatMap doesn't express it very nicely, or efficiently.
> 
> We've recently added another form of flatMap, mapMulti, which is a lot 
> more efficient; in that version, your example would be:
> 
>      .mapMulti((e,s) -> { if (e instanceof P(b)) s.accept(b); })
> 
> If `void` were a type, we could express this as an expression lambda:
> 
>      .mapMulti((e,s) -> e instanceof P(b) ? s.accept(b) : void )
> 
> A variant of mapMulti optimized for zero-or-one (which would be more 
> sensible when Optional is a primitive class) might be:
> 
>      .mapMaybe(e -> Optional.ofNullable(e instanceof P(b) ? b : null) )
> 
> where mapMaybe takes a T -> Optional<U>.
> 
> Note that the use of patterns here is limited to the case where you are 
> going to package up all the bindings into a single value.
> 
> There's some other possibilities but I want to think about them some 
> more before discussing them.
> 
> 
> On 1/19/2021 7:30 PM, Johannes Kuhn wrote:
>> Turns out I sometimes write code that looks like this:
>>
>>     foos.stream().filter(e -> e instanceof Foo).map(e -> (Foo) e)...
>>
>> or
>>
>> foos.stream().filter(Foo.class::isInstance).map(Foo.class::cast)...
>>
>> Nicolas Fränkel has even written a blog post about this[1].
>>
>> Anyway, this can be expressed with a single stream operation:
>>
>>     foos.stream().flatMap(e -> e instanceof Foo foo ? Stream.of(foo) : 
>> Stream.of())...
>>
>> I expect that form to work with any pattern in the future.
>> But it doesn't look great.
>>
>> Are there any plans around this?
>> Or is this something patterns shouldn't be used for?
>>
>> In a more general way - will there be a way to pass a pattern as an 
>> argument to some other function?
>>
>> - Johannes
>>
>>
>>
>> [1]: https://blog.frankel.ch/changing-coding-habits-stream-friendly/
> 


More information about the amber-dev mailing list