> On Dec 5, 2017, at 10:17 AM, Brian Goetz <[email protected]> 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