flatMap ambiguity (original) (raw)

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:

Stream 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)->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:

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:

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 sink) -> ...").

—Dan



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