9.1 Equatables
Any value is equatable. Implementing the Equatable interface customizes the way that instances of a class are compared for == or is_now and hashed for maps and sets that use == or is_now.
An interface that a class can implement (publicly or privately) to customize the way its objects are compared for == or is_now and hashed for maps and sets that use == or is_now. The interface has two methods that must be overridden for ==, and two methods for is_now whose default implementations use the methods for ==:
equals(other, recur): Takes another object that is an instance of the same class (or a subclass), and returns a non-#false value if the objects are equal in the sense of ==, #false otherwise. Use the given recur function to compare components of the two objects, instead of using == on the components.
If a class has mutable fields whose state is externally observable, take care not to treat objects as == if they should be equivalent only by is_now. Override both the equals and now_equals to distinguish == and is_now equality.
If two objects are equal in the sense of ===, then they are automatically also equal by ==. An equals method implementation is never called on an obejct with itself as other.
hash_code(recur): Returns a hash code for the object, which is an exact integer. The hash code should be consistent with equality via ==. Use recur to compute hash code for components of the object, and use the functions Equatable.hash_code_combine and Equatable.hash_code_combine_unordered to combine component hash codes.
If a class has mutable fields, the hash code produced by hash_code normally should return the same result as Equatable.identity_hash. Override now_hash_code to implement hashing consistent with is_now.
now_equals(other, recur): Like equals, but for equality in the sense of is_now. The default implementation of this method calls the equals method; it passes along the given recur function, which means that is_now will used for nested comparisons (assuming that the called equals method uses recur as it should).
now_hash_code(recur): Like hash_code, but for equality in the sense of is_now. The default implementation of this method calls the hash_code method; it passes along the given recur function, which means that nested hashing will create is_now-compatible results (assuming that the called hash_code method uses recur as it should).
A class gets a default equality implementation that recurs to compare fields for == only if the class has no mutable fields. When the class has mutable fields, is default equality implementation for == uses === comparisons. The default equality implementation always recurs to fields for is_now comparisons.
The Equatable interface normally should be implemented privately, so that the methods do not have to check what class other instantiates or whether recur is a function.
class Posn(x, y):
method dist():
cache := v
v)
// since `cache` is mutable, the default equality
// comparison would only make `===` objects equal
Equatable.hash_code_combine(recur(x), recur(y))
> Posn(3, 4) == Posn(3, 4)
#true
function | ||
| ||
| ||
function | ||
|
See Equatable for an example.