flatMap ambiguity

Dan Smith daniel.smith at oracle.com
Tue Feb 26 13:47:10 PST 2013


A thread on lambda-dev highlighted a problem with the overloading of flatMap:

<R> Stream<R> flatMap(FlatMapper<? super T, R> mapper)
 IntStream flatMap(FlatMapper.ToInt<? super T> mapper)
LongStream flatMap(FlatMapper.ToLong<? super T> mapper)
DoubleStream flatMap(FlatMapper.ToDouble<? super T> mapper)

These functional interfaces have corresponding descriptors:

(T, Consumer<R>)->void (R is inferred)
(T, IntConsumer)->void
(T, LongConsumer)->void
(T, DoubleConsumer)->void

This violates the general rule that overloading with functional interfaces of the same shape shouldn't use different parameter types.  Various ambiguities result:

- "(x, sink) -> sink.accept(10)" is compatible with all the primitive consumers, and we have no way to disambiguate (the new most-specific rules handle this sort of thing with return types, but are not designed to decide which type is "better" for an arbitrary block of code).

- "(x, sink) -> sink.accept(22.0)" is compatible with "(T, DoubleConsumer)->void", and leads "(T, Consumer<R>)->void" to be provisionally applicable -- we don't check the body at all in that case, until we've had a chance to look at the target type of the 'flatMap' invocation and figure out what R is supposed to be.  So, again, an ambiguity will occur.

It would probably be best to give the primitive versions distinct names.

---

Note also that an invocation like the following will always produce a Stream<Object>:

stream.flatMap((x, sink) -> sink.accept("x")).filter(...)....

Inference is forced to resolve R without knowing anything about it, and so it must go with the default "Object".

The only way to get useful information about R is to derive bounds from the body of the lambda, and that's simply not something we can do in general.

I don't know what to recommend in this case, except perhaps that this method inherently depends on some explicit typing (e.g., "(String x, Consumer<String> sink) -> ...").

—Dan


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