Q on Patterns and Streams
Brian Goetz
brian.goetz at oracle.com
Wed Jan 20 14:54:24 UTC 2021
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