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