RFR: 8317993: Add capturing factories to classes in java.util.function package [v5]

Maurizio Cimadamore mcimadamore at openjdk.org
Wed Oct 18 17:49:43 UTC 2023


On Wed, 18 Oct 2023 09:00:09 GMT, Per Minborg <pminborg at openjdk.org> wrote:

>> This PR proposes to add a number of "capturing factories" in classes in the `java.util.function` package.
>> 
>> The PR additionally (an optionally) proposes to add a new function `UnaryOperator::andThenUnary` to allow composition while retaining the `UnaryOperator` type.
>> 
>> With the new changes, it is possible to write code like this (example from `java.util.function.Function`):
>> 
>> 
>> // Resolve ambiguity
>> var function = Function.of(String::isEmpty); // Function<String, Boolean>
>> var predicate = Predicate.of(String::isEmpty); // Predicate<String>
>> 
>> // Fluent composition
>> var chained = Function.of(String::length)       // Function<String, Integer>
>>                    .andThen(Integer::byteValue);      // Function<String, Byte>
>> 
>> 
>> Please see the original bug report for a comprehensive description of these proposed changes.
>> 
>> Note: It is not the objective to promote `var` declaration or to prevent previous ways of capturing lambdas and method references. The comments in the code above is for explaining the binding and once that becomes obvious, such comments are likely to not appear in real code. Users that prefers having a normal type declaration can still do that.
>> 
>> Note: Functional interfaces of primitives have not been considered (in this round). Otherwise, functional interfaces that might be ambiguous or that supports composition have been included. Hence, `Supplier` did not get a factory method.
>
> Per Minborg has updated the pull request incrementally with one additional commit since the last revision:
> 
>   Pretty

With my language hat on, there are two things that are problematic here:
1. lack of target-typing propagation can cause some use-site to be less fluent (as they have to break up different higher-order method calls)
2. the overload resolution logic for higher-order methods is sometimes overly conservative - e.g. it will refuse to look at the body of a lambda expression with implicit parameter types if there's two possible target types, even though the two targets agree on the inferred parameter types (this problem is described in the third part of https://openjdk.org/jeps/302).

Now, addressing (1) require big changes to the inference scheme (it is especially problematic if a "yet to be inferred" type-variable acts as a receiver for the subsequent method in the chain).

But addressing (2) is far more doable, and should lead to a nice usability boost in a lot of situations where the language currently says "sorry, ambiguous". And it feels this is the main motivation for adding the new APIs in the first place. If so, perhaps considering a language change/enhancement could provide better return on investment?

-------------

PR Comment: https://git.openjdk.org/jdk/pull/16213#issuecomment-1769043653


More information about the core-libs-dev mailing list