Comparator combinators
Sam Pullara
spullara at gmail.com
Wed Aug 21 14:18:05 PDT 2013
I think the IntFunction version will be used more than any other
version. We could probably name that one comparing and name the other
ones with their types, e.g. comparingObject.
Sam
> On Aug 21, 2013, at 2:09 PM, Henry Jen <henry.jen at oracle.com> wrote:
>
> Seems the consensus is converging to disambiguate with the method name, which I am OK with. In fact, we had done that before and revert back because people don't like it.
>
> As mentioned several times, the not-intended boxing is the main concern. While I understand that IDE could help, I don't like to assume people will be using one(although most likely they are).
>
> How often will we need to add these explicit type? Is that type harder to figure out than knowing what we are comparing?
>
> Cheers,
> Henry
>
>> On Aug 21, 2013, at 11:28 AM, Brian Goetz <brian.goetz at oracle.com> wrote:
>>
>> Waiting for input on this.
>>
>> I'm torn. On the one hand, we'd be publishing a new, lambda-centric API that doesn't conform to our "safe overloading" rules, and for which users would have to use explicit lambdas in the cases where method references aren't practical.
>>
>> On the other, if we rename the primitive versions to comparingXxx/thenComparingXxx, we're creating a different sort of risk -- users will say
>>
>> comparing(Person::getAge)
>>
>> and get boxing when they didn't intend (this is comparing(Function<Person,Integer>), when they probably wanted comparingInt(ToIntFunction<Person>)). Though this would be easy for IDEs to detect and suggest a replacement.
>>
>> I think the responsible thing to do is still probably to disambiguate by method name -- comparingInt, thenComparingLong, etc. Which isn't pretty but seems to be the new equilibrium (overloading and inference are in opposition; adding more inference means we can tolerate less overloading.)
>>
>> If there's no input, an executive decision will be made...
>>
>>
>>
>>> On 8/14/2013 3:49 PM, Brian Goetz wrote:
>>> This may well be our last API loose end...
>>>
>>> We currently have a pile of Comparator combinators, all currently called
>>> comparing() or thenComparing(). Regardless of whether we choose to go
>>> forward with the simplified overloading plan, these overloads have a
>>> problem: for implicit lambdas, we can't distinguish between
>>>
>>> comparing(T->U)
>>> and
>>> comparing(T->int)
>>>
>>> because we don't type-check the body of the lambda until we do overload
>>> selection, and don't do overload selection based on whether there are
>>> type errors in the body (this was roundly rejected as being too
>>> brittle). So for lambdas like:
>>>
>>> comparing(x -> x.size())
>>>
>>> we've got a circularity -- even under the older, more complex scheme.
>>>
>>> We'd thought perhaps that, if we adopted the heuristic that we can
>>> eagerly give a type to method reference that refers to a non-overloaded
>>> method (e.g., Person::getAge), then cases like
>>>
>>> comparing(Person::getAge)
>>>
>>> can be handled, and this might take some of the pressure off the problem.
>>>
>>> For lambdas (with either approach) you can always get what you want with
>>> an explicit lambda:
>>>
>>> comparing((Person p) -> p.getAge())
>>>
>>> since this can be type-checked early.
>>>
>>> So the question is, is this good enough, even though it falls afoul of
>>> the overloading guidelines for implicit lambdas? Or, should we mangle
>>> the names of the methods?
>>>
>>> This question comes down to whether we think its better to force
>>> everyone to explicitly pick a method, but then supporting implicit lambdas:
>>>
>>> comparingInt(x -> x.size())
>>>
>>> or forcing users to use non-ambigous method refs or explicit lambdas:
>>>
>>> comparing(Person::getAge)
>>> or
>>> comparing((Person p) -> p.getAge())
>>>
>>> Which disambiguation approach is worse?
>
More information about the lambda-libs-spec-observers
mailing list