Thanks rdeits. I’m not familiar with any of this.
I want this to work for any number, so I type with Number
, right?
struct Foo
a::Vector{Number}
end
On the one hand:
julia> Base.isequal(x::Foo, y::Foo) = x.a == y.a
julia> Foo([1]) == Foo([1])
false
On the other hand:
julia> Base.:(==)(x::Foo, y::Foo) = x.a == y.a
julia> Foo([1]) == Foo([1])
true
So there’s a subtle difference between ==
and isequal
.
And what is this for?
julia> Base.hash(x::Foo, h::UInt) = hash(x.a, h)
julia> hash(Foo([1]))
0x8c5e337b3aca66f1
julia> hash(Foo([1])) == hash(Foo([1]))
false
So while now Foo([1]) == Foo([1])
has become true
, we have hash(Foo([1])) == hash(Foo([1]))
is false
. What do I do now?
What I gather from the docs is that if you create your own definition of equality between two things, you would also make sure that the two things are mapped to the same hash. As for what a hash is, I found this definition:
A hash is a function that converts one value to another. […] hashes are used to index data. Hashing values can be used to map data to individual “buckets” within a hash table. Each bucket has a unique ID that serves as a pointer to the original data. This creates an index that is significantly smaller than the original data, allowing the values to be searched and accessed more efficiently. (source)
The docs are short enough to be quoted in full:
Base.hash — Function
hash(x[, h::UInt])
Compute an integer hash code such that `isequal(x,y)` implies `hash(x)==hash(y)`. The optional second argument `h` is a hash code to be mixed with the result.
New types should implement the 2-argument form, typically by calling the 2-argument `hash` method recursively in order to mix hashes of the contents with each other (and with `h`). Typically, any type that implements `hash` should also implement its own `==` (hence `isequal`) to guarantee the property mentioned above. Types supporting subtraction (operator `-`) should also implement [`widen`](@ref), which is required to hash values inside heterogeneous arrays.