The uniqueness of complex keywords in Go, but not in Julia?

In GO, when I use struct as a key for a map, there is a unity of keys.

For example, the following code creates a map with one key: map [{x 1}: 1]

package main

import (
    "fmt"
)

type MyT struct {
    A string
    B int
}

func main() {

    dic := make(map[MyT]int)

    for i := 1; i <= 10; i++ {
        dic[MyT{"x", 1}] = 1
    }

    fmt.Println(dic)
}

// result : map[{x 1}:1]

I tried to do the same in Julia, and I had a strange surprise:

This Julia code, similar to GO, produces a dictionary with 10 keys!

    type MyT
        A::String
        B::Int64
    end

    dic = Dict{MyT, Int64}()

    for i in 1:10
        dic[MyT("x", 1)] = 1
    end

    println(dic)
    # Dict(MyT("x",1)=>1,MyT("x",1)=>1,MyT("x",1)=>1,MyT("x",1)=>1,MyT("x",1)=>1,MyT("x",1)=>1,MyT("x",1)=>1,MyT("x",1)=>1,MyT("x",1)=>1,MyT("x",1)=>1)

    println(keys(dic))
    # MyT[MyT("x",1),MyT("x",1),MyT("x",1),MyT("x",1),MyT("x",1),MyT("x",1),MyT("x",1),MyT("x",1),MyT("x",1),MyT("x",1)]

So what have I done wrong?

Thanks @DanGetz for the solution!

immutable MyT     # or struct MyT with julia > 0.6
    A::String
    B::Int64
end

dic = Dict{MyT, Int64}()

for i in 1:10
    dic[MyT("x", 1)] = 1
end

println(dic)         # Dict(MyT("x", 1)=>1)
println(keys(dic))   # MyT[MyT("x", 1)]
+6
source share
3 answers

, , , , . , - , , . , - , . , MyT , :

immutable MyT # `struct MyT` in 0.6
    A::String
    B::Int64
end

dic = Dict{MyT, Int64}()

for i in 1:10
    dic[MyT("x", 1)] = 1
end

julia> dic
Dict{MyT,Int64} with 1 entry:
  MyT("x", 1) => 1

julia> keys(dic)
Base.KeyIterator for a Dict{MyT,Int64} with 1 entry. Keys:
  MyT("x", 1)

, String Int, -, , , . , , , , 0,6 struct mutable struct - , , , - .

@ntdef, , Base.hash. , (, , ​​, ):

  • Base.hash, , Base.hash(::T, ::UInt).
  • Base.hash(::T, ::UInt) UInt.
  • Base.hash, Base.== .

, ( Julia MyT):

type MyT # `mutable struct MyT` in 0.6
    A::String
    B::Int64
end

import Base: ==, hash

==(x::MyT, y::MyT) = x.A == y.A && x.B == y.B

hash(x::MyT, h::UInt) = hash((MyT, x.A, x.B), h)

dic = Dict{MyT, Int64}()

for i in 1:10
    dic[MyT("x", 1)] = 1
end

julia> dic
Dict{MyT,Int64} with 1 entry:
  MyT("x", 1) => 1

julia> keys(dic)
Base.KeyIterator for a Dict{MyT,Int64} with 1 entry. Keys:
  MyT("x", 1)

, AutoHashEquals , . , , type @auto_hash_equals:

using AutoHashEquals

@auto_hash_equals type MyT # `@auto_hash_equals mutable struct MyT` in 0.6
    A::String
    B::Int64
end

:

  • , , , .

  • , , -.

  • - , AutoHashEquals.

+9

. , - /Dict. go , . , , . . .

Go

Julia go, , MyT :

func main() {

    dic := make(map[MyT]int)
    pdic := make(map[*MyT]int)

    for i := 1; i <= 10; i++ {
        t := MyT{"x", 1}
        dic[t] = 1
        pdic[&t] = 1
    }

    fmt.Println(dic)
    fmt.Println(pdic)
}

pdic MyT . MyT, , , . :

map[{x 1}:1]
map[0x1040a140:1 0x1040a150:1 0x1040a160:1 0x1040a180:1 0x1040a1b0:1 0x1040a1c0:1 0x1040a130:1 0x1040a170:1 0x1040a190:1 0x1040a1a0:1]

play.golang.org. Julia (. ) , .

Go Behavior Julia

Julia Base.hash(::K, ::UInt) - Dict{K,V}. , object_id, . go Julia, hash , struct:

Base.hash(t::MyT, h::Uint) = Base.hash((t.A, t.B), h)

, == , , hash(x)==hash(y) isequal(x,y), .

- MyT immutable. , MyT , object_id. :

immutable MyT
    A::String
    B::Int64
end

dic = Dict{MyT, Int64}()

for i in 1:10
    dic[MyT("x", 1)] = 1
end

dic[MyT("y", 2)] = 2

println(dic) # prints "Dict(MyT("y",2)=>2,MyT("x",1)=>1)"
+4

: @StefanKarpinski. Base.hash UInt, , . , .

, 10 , , Julia hash dict. , . (A,B) , hash , - :

Base.hash(x::MyT) = (x.A, x.B)

Go, Dict.

hash.

Hope this helps!

+2
source

All Articles