Value-Based Classes - equals/hashCode
Nicolai Parlog
nipa at codefx.org
Sun Feb 15 19:53:35 UTC 2015
> Hope this helps.
Yes it does. Ignoring the sand, I'd say I got it.
And I assume this is important because extending equality to the state
of (instead of the reference to) non-value-ish instances threatens the
interchangeability* of values?
* "Instances of a value-based class are freely substitutable when
equal, meaning that interchanging any two instances x and y that are
equal according to equals() in any computation or method invocation
should produce no visible change in behavior."
On 14.02.2015 22:03, Brian Goetz wrote:
>> But yes, also, what's up with that? One interpretation is surely
>> that the StringHolder's string (to stick with that example) can
>> not be accessed as it is "any other object". On the other hand
>> the string is surely part of the holder's state which is
>> expressively allowed to be used for that computation. So what is
>> it?
>
> Which brings us back to the fundamentally murky part -- what
> comprises the state of an object?
>
> In languages like Lime (a Java-like language designed for GPU
> computation), a value type must be "values all the way down".
> (Their primitive data type is "bit"; everything else is defined as
> composites of bit.) This is a beautiful and clean way to define
> things, but not applicable to the practical problem of adding true
> values to a mutation-happy language like Java; even simple types
> like String require some mental gymnastics to see them as
> value-like (String stores characters in an array, which is mutable,
> but just not mutated after initialization, and even has a
> lazily-initialized, mutable field for the hash code (if that's not
> bad enough, this field is updated using data races!)) But not
> being able to have String as a component of a value would be silly,
> and no one disputes that strings are "value-ish". But the clean
> definitions don't apply.
>
> We found ourselves with a related problem when trying to define
> the constraints on behavioral parameters passed to stream methods
> (e.g., the Predicate passed to Stream.filter). The "obvious"
> restrictions were "side-effect free" or "pure function". But
> neither of these is the right answer; both are unnecessarily
> restrictive. (Printing a debug message or updating a history
> buffer are acceptable side effects; looking up data in a mutable
> but not-mutated-during-the-query HashMap is an acceptable
> compromise of purity.) We settled on a murky definition of
> "non-interfering" and "stateless", knowing full well that our
> definitions are built on sand, but tried to capture the true spirit
> of the restriction, which is "don't depend on stuff that might
> change during the calculation."
>
> Said sand includes notions like "what is the state of an object".
>
> Here's a stab at thinking about this, which I'm sure is wrong, but
> might be a helpful start. Say a value-ish class C has fields
> c_1..c_n. Now let's try and define S(C), the variables that
> comprise the "state" of C. S(C) includes: - \forall_i c_i, if c_i
> is a primitive - \forall_i S(c_i), if c_i is a reference to a
> value-ish class - \forall_i c_i, if c_i is a reference to a
> non-value-ish class
>
> In other words, if a value contains other values, we recursively
> include the dependent value in the state; if a value contains
> references to non-values, we can only include the that reference
> (references are values!), but not any state reachable through that
> reference. (We wave our hands and magically define certain
> otherwise-problematic classes (like String) to be value-ish.)
>
> So, in the following class:
>
> final class Urk { private final MutableStuff mc;
>
> private Urk(MutableStuff mc) { this.mc = mc; } public Urk
> make(MutableStuff mc) { return new Urk(mc); }
>
> public boolean equals(Object other) { return (other instanceof
> Urk) && ((Urk) other).mc == mc; }
>
> // similar for hashCode }
>
> I would argue this is following the rules; Urk's state includes
> the *reference to* mc, but not the *state of* mc. If Urk were to
> dive into the state of mc, then it would have crossed the line.
>
> Hope this helps.
>
--
PGP Key:
http://keys.gnupg.net/pks/lookup?op=vindex&search=0xCA3BAD2E9CCCD509
Web:
http://codefx.org
a blog about software development
http://do-foss.de
Free and Open Source Software for the City of Dortmund
Twitter:
https://twitter.com/nipafx
More information about the valhalla-dev
mailing list