Stream.flatMap reference ambiguity
paul.sandoz at oracle.com
Wed Feb 27 01:45:32 PST 2013
On Feb 27, 2013, at 1:23 AM, Dan Smith <daniel.smith at oracle.com> wrote:
> On Feb 26, 2013, at 2:57 PM, Zhong Yu <zhong.j.yu at gmail.com> wrote:
>>> I think the core problem is the API (in general, it's best to avoid overloading with functional interfaces that have different parameter types),
>> I don't quite understand what you mean, can you clarify?
> The type of the second parameter of the lambda depends on the overload resolution choice -- it may be a Consumer<String>, or a IntConsumer, or a LongConsumer, or a DoubleConsumer. So overload resolution is given four different possible typings of the parameters of the lambda, and is asked to choose the "best" one.
> As I've pointed out, this is a pretty brittle situation, and while the compiler is able to do a certain degree of disambiguation, there's a good chance that clients of the API will encounter ambiguities.
> For example:
> stream.flatMap((x, sink) -> sink.accept(x.length()));
> 'x.length()' is an int, meaning the intent is probably to represent an IntConsumer; but the compiler is not equipped to make that sort of judgement, and would be equally happy with a LongConsumer, or a DoubleConsumer, or a Consumer<Integer>, ...
> Hence, API designers should generally avoid overloading that relies on disambiguating between functional interfaces of the same arity that have different parameter types.
So could we do either (or both) of the following:
- change the Int/Long/DoubleConsumer.accept methods to be acceptInt/Long/Double
- change the flatMap methods to be flatMapInt etc.
We don't always disambiguate the method name of the functional interface from its primitive specialization counterpart e.g. when the return type is void. What you say above suggests that we should since other APIs using these interfaces are gonna rub up against similar issues.
More information about the lambda-dev