Difficulty of compareTo on floats/doubles

Frank van Heeswijk fvheeswijk at outlook.com
Fri Aug 1 09:05:11 UTC 2014


Alex,

You gave the following class setup:

class Bar {
   int f;
   public Bar(int f){ this.f = f; }
   public boolean equals(Object that){ return (that instanceof Bar) &&
((Bar)that).f == f; }
}
 
final __ByValue class Foo {
    int x;
    Bar y;
}
 
 
Foo a = __MakeValue(5, new Bar(10));
Foo b = __MakeValue(5, new Bar(10));

Correct me if wrong, but I was under the impression that value types could not hold object type references.
My reasoning would be that the real values are stored directly on the stack, instead of a reference.

Could anyone confirm or deny this?

- Frank

> Date: Thu, 31 Jul 2014 15:25:30 -0700
> Subject: Re: Difficulty of compareTo on floats/doubles
> From: timeroot.alex at gmail.com
> To: john.r.rose at oracle.com
> CC: valhalla-dev at openjdk.java.net
> 
> So the current state is that for...
> primitives:
>     == and != performs bitwise comparison
>     equals() doesn't exist
> Objects:
>     == and != perform identity testing
>     equals() is a method that can be overriden
> 
> With regards to equality on value types, it sounds like the main proposals
> are...
> values, option 1:
>     == performs elementwise testing, via "vcmp"
>     equals() defaults to vcmp, but can be overridden
> 
> values, option 2:
>     == and equals() perform elementwise testing, via "vcmp". equals() is
> final.
> 
> values, option 3:
>     == doesn't exist on the unboxed values.
>     equals() defaults to vcmp, but can be overridden
> 
> And then on polymorphic generics that could be primitive, value, or Object,
> there are
> generics, option 1:
>     == will perform just as == would on the corresponding
> Object/primitive/value
>     equals() will call the method on the Object/value, and
> Float.equals()/Integer.equals()/etc. on primitives
> 
> generics, option 2:
>     == is an identity check on Objects, and equals() on primitive/value
>     equals() will call the method on the Object/value, and
> Float.equals()/Integer.equals()/etc. on primitives
> 
> generics, option 3:
>     == doesn't exist on polymorphic variables
>     equals() will call the method on the Object/value, and
> Float.equals()/Integer.equals()/etc. on primitives
> 
> and the situation you're describing is option 1 for values, and option 3
> for generics. (The numbering is arbitrary, of course).
> Would allowing equals to be overridden be worth it, on value types?
> Although certainly mostly a lack of imagination, I feel like the use cases
> to redefine it would be limited -- and there is one other thing to
> consider, of how the equality check should recurse onto objects members of
> the value type. For instance, given a situation like
> 
> class Bar {
>    int f;
>    public Bar(int f){ this.f = f; }
>    public boolean equals(Object that){ return (that instanceof Bar) &&
> ((Bar)that).f == f; }
> }
> 
> final __ByValue class Foo {
>     int x;
>     Bar y;
> }
> 
> 
> Foo a = __MakeValue(5, new Bar(10));
> Foo b = __MakeValue(5, new Bar(10));
> 
> System.out.println(a == b);
> System.our.println(a.equals(b));
> 
> Then my first expectation would be for them to print "false" and "true",
> respectively. That is, if "==" were a vcmp, it would check x's for integer
> bitwise equality, and the reference y the same way. The "equals" method I
> would intuitively expect to do similar bitwise comparison on x, but a call
> to y.equals(). This follows along with the general thought process that
> when I'm treating it like an int I want a quick and "dumb" equality check,
> whereas the more class-seeming equals() call is something I can expect to
> be a "deep" check. I may be alone in expecting this. :) But if others agree
> that it would be a logical behavior, then I would support defining == to be
> recursive == on reference fields, and equals() to be a (probably final)
> method doing the above.
> 
> -- Alexander Meiburg
> 
> 
> 2014-07-31 13:56 GMT-07:00 John Rose <john.r.rose at oracle.com>:
> 
> > On Jul 31, 2014, at 12:43 PM, Alex M <timeroot.alex at gmail.com> wrote:
> >
> > > strange problems
> >
> > The essential point here is discussed in passing (see "simple
> > relationals") in the value type prospectus.
> >   http://cr.openjdk.java.net/~jrose/values/values.html
> >
> > Yes, there are a lot of these strange problems that arise from forcing
> > both primitives and objects under one type bound.
> >
> > More generally, the semantic oddities of "==" for float, double, and
> > references make it very tricky indeed to apply "==" (and other operators,
> > notably "+") to extremely polymorphic variables bounded by "any".
> >
> > Although it may not be practical in the end, my personal preference would
> > be to deprecate or disallow operators on polymorphic variables, and express
> > everything with method invocation.
> >
> > Method invocation on a non-reference value can be uniformly and simply
> > defined by delegation to a boxed version of the value. If we define new box
> > types (not impossible though difficult) we can take extra care to have the
> > ad hoc polymorphism be as consistent as possible across the expanded range
> > of types.  We provide for such consistency already in the documentation of
> > interfaces like Comparable and (as Joe explained) methods like
> > Double.compareTo.
> >
> > Pre-existing boxes are probably not adequate to this.  Null references may
> > also require a "boxing" rule of some sort.
> >
> > See also the "vcmp" instruction in the value types prospectus.  For value
> > types we think we can make a compatible story of how to cope with "==" and
> > ".equals":  "==" is bitwise and ".equals" is a method call (possibly boxed,
> > but the user cannot observe whether that happens).
> >
> > Bottom lines:  Consistent ad hoc polymorphism is hard, especially when
> > unifying legacy types.  And see "vcmp" for bitwise semantics and extend it
> > if necessary to primitives.  But try hard to do most things in terms of
> > methods, which is more flexible and explicit.
> >
> > — John
 		 	   		  


More information about the valhalla-dev mailing list