> On Dec 5, 2017, at 10:17 AM, Brian Goetz <brian.go...@oracle.com> wrote:
> 
> At some level, this goes to the heart of "why should records, and not tuples, 
> be our 'plain data' abstraction."  Adding behavior to a record, **where that 
> behavior is derived strictly from the state**, is easy and natural.
> 
> You can look at the "but I have to write compareTo" issue as glass 90% full 
> or 10% empty; a record starts life with a sensible ctor, dtor, accessors, 
> equals, hashCode, and toString.  So adding compareTo is pretty easy.  Note 
> also that there's no way we can reasonably derive compareTo from the state 
> description, since (a) not all state fields are going to be relevant for 
> ordering comparison and (b) the order in which they are declared may not be 
> the natural comparison order.  So somewhere in the program the user is going 
> to have to write down that "a Person is compared by (lastName, firstName)", 
> somehow.
> 
> We could of course invent all sorts of shorthands, but I think the 
> return-on-complexity there is limited, as the natural way to say this is 
> pretty straightforward:
> 
>     record Person(String first, String last, String age)
>             implements Comparable<Person> {
> 
>         private static final Comparator<Person> cc
>             = 
> Comparators.comparing(Person::last).thenComparing(Person::first);
> 
>         public int compareTo(Person other) {
>             return cc.compareTo(other);
>         }
>     }
> 
> But, let's not get distracted by Billy, we care about semantics. Where are 
> the pitfalls you see of this approach where it might run afoul of the 
> "consistency between equals and compareTo is recommended" dictum?

If the automatically generated `equals` method examines all fields but the 
`compareTo` method does not, then there can be cases where `compareTo` says 
that two objects are equal but `equals` says they are unequal.

        Example:

                Person me = new Person(“Guy”, “Steele”, 63);
                Person myDad = new Person(“Guy”, “Steele”, 89);

                me.equals(myDad) ==> false
                me.compareTo(myDad) ==> 0

One possible solution is simply a programming discipline or documentation 
suggestion that says that if you write a `compareTo` method, with or without a 
`Comparator`, you should at least think about whether to provide an explicit 
definition of `equals` as well to ensure that they are consistent.

In fact, we already have such a note in the documentation for `Comparator`:

    The natural ordering for a class C is said to be consistent with equals if 
and only if e1.compareTo(e2) == 0 has the same boolean value as e1.equals(e2) 
for every e1 and e2 of class C. . . .

    It is strongly recommended (though not required) that natural orderings be 
consistent with equals. . . .

    Virtually all Java core classes that implement Comparable have natural 
orderings that are consistent with equals.

So I think the question that Rémi raises has to do with whether the language 
design going forward can/should better assist programmers to address this 
already existing recommendation.

—Guy

Reply via email to