ensure that 'hash' is unchangeable through contract in 'Object'
Closed this issue · 1 comments
hash
should never change for an instance of Object
. Having a changeable hash
implies that hash sets/maps cannot efficiently and easily satisfy the contract in Iterable.contains
.
There is an important consequence implied by this change. That is, for every two non‐variable references obj1
and obj2
, the expression obj1 == obj2
should never change its value.
That consequence would be problematic if Ceylon was Java, but since classes with mutable state are considerably rare in Ceylon, I don’t think it’s that this addend to the contract of Object
would actually be intrusive.
That is, if a class does have mutable state, one can simply:
- not rely on it for equality.
- rewrite the program to not use stateful classes.
- use the default implementation from
Basic
/Identifiable
.
To illustrate the point, in case it isn’t clear:
import ceylon.collection {HashSet}
class Mutable(shared actual variable Integer hash)
{
equals(Object that) => that is Mutable && this.hash == that.hash;
}
shared void run()
{
value mutable = Mutable(0);
value set = HashSet{mutable};
mutable.hash = 12;
assert(mutable in set); // throws
}
In this case I’m mutating hash
directly, however, if hash
was a getter depending on a variable attribute, the same effect would be achieved.
I don't think it's possible to enforce this, without doing something incredibly heavy-handed and unreasonable. Closing.