Immutables automatically have value-based hashing defined for them. That's
a dangerous default for mutable values since it makes it easy to stick
something in a dict, then mutate it, and "lose it", e.g.:

type Mutable
     x::Int
end

Base.hash(m::Mutable, h::UInt) = hash(m.x, h + (0x17d88030d571c6e3 % UInt))
==(m1::Mutable, m2::Mutable) = m1.x == m2.x

julia> m = Mutable(0)
Mutable(0)

julia> d = Dict()
Dict{Any,Any} with 0 entries

julia> d[m] = "here"
"here"

julia> m.x = 1
1

julia> d[m]
ERROR: KeyError: Mutable(1) not found
 in getindex at dict.jl:695

julia> d
Dict{Any,Any} with 1 entry:
  Mutable(1) => "here"


On Thu, Jul 16, 2015 at 12:35 PM, Seth <catch...@bromberger.com> wrote:

>
>
> On Thursday, July 16, 2015 at 9:25:01 AM UTC-7, Matt Bauman wrote:
>>
>> On Thursday, July 16, 2015 at 12:19:25 PM UTC-4, milktrader wrote:
>>>
>>> Also, back to the OP question, is the correct solution to simply define
>>>
>>>  Base.hash(f::Foo) = f.x
>>>
>>
>> No, I'd define Base.hash(f::Foo) = hash(f.x, 0x64c74221932dea5b), where
>> I chose the constant by rand(UInt).  This way it won't collide with other
>> types.  I really need to spend a bit more time with my interfaces chapter
>> and add this info there.
>>
>>
> How would you do this (in a performant way) for a type that has two
> internal values? That is, I have
>
> immutable Foo{T}
>    x::T
>    y::T
> end
>
>
> Obviously, the hash should be based on both values, right? I could do
>
> Base.hash(f::Foo) = hash(hash(f.x, f.y), 0x64c74221932dea5b)
>
> But that calls hash twice. (Is this even necessary with immutables?)
>
>

Reply via email to