# Unexpected result from ==

**URL:** <https://discourse.julialang.org/t/unexpected-result-from/91499>\
**Category:** General Usage\
**Created:** [December 10, 2022, 4:12am UTC](https://discourse.julialang.org/t/unexpected-result-from/91499 "2022-12-10T04:12:47Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Stephen\_Vavasis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stephen_vavasis/32/3389_2.png) [@Stephen\_Vavasis](https://discourse.julialang.org/u/Stephen_Vavasis)\
**Post date:** [December 10, 2022, 4:12am UTC](https://discourse.julialang.org/t/unexpected-result-from/91499/1 "2022-12-10T04:12:48Z")

</div>

A dictionary in my code is not working because keys that are supposed to be equal are comparing as unequal. Here is a snippet (Julia 1.8.2). Is this a bug, or am I misunderstanding how == is supposed to work?

```julia
julia> abstract type ET end

julia> struct ET1 <: ET
       end

julia> struct SK1{T <: ET}
       nl::Vector{Int}
       end

julia> k1 = SK1{ET1}([4,3,5])
SK1{ET1}([4, 3, 5])

julia> k2 = SK1{ET1}([4,3,5])
SK1{ET1}([4, 3, 5])

julia> k1 == k2
false

```

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [December 10, 2022, 4:22am UTC](https://discourse.julialang.org/t/unexpected-result-from/91499/2 "2022-12-10T04:22:47Z")

</div>

`==` on structs by default calls `===` on it’s members. If you want different behavior, you need to overload `==`.

---

<div class="post-metadata">

**Author:** ![albheim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/albheim/32/34660_2.png) [@albheim](https://discourse.julialang.org/u/albheim)\
**Post date:** [December 10, 2022, 4:56am UTC](https://discourse.julialang.org/t/unexpected-result-from/91499/3 "2022-12-10T04:56:33Z")

</div>

And to expand on oscars answer, this is what the docstring for `===` says

```julia
help?> ===
search: === == !==

  ===(x,y) -> Bool
  ≡(x,y) -> Bool

  Determine whether x and y are identical, in the sense that no program could
  distinguish them. First the types of x and y are compared. If those are identical,
  mutable objects are compared by address in memory and immutable objects (such as
  numbers) are compared by contents at the bit level. This function is sometimes
  called "egal". It always returns a Bool value.

  Examples
  ≡≡≡≡≡≡≡≡≡≡

  julia> a = [1, 2]; b = [1, 2];

  julia> a == b
  true

  julia> a === b
  false

  julia> a === a
  true

```

so it makes sense since the objects are not the same, they just contain the same values.

If you want to check if they contain the same value, you could compare the content instead

```julia
k1.nl == k2.nl

```

or you could overload `==` for your type if want to directly compare them

```julia
Base.:(==)(a::SK1, b::SK1) = a.nl == b.nl
```

---

<div class="post-metadata">

**Author:** ![uniment](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/uniment/32/24532_2.png) [@uniment](https://discourse.julialang.org/u/uniment)\
**Post date:** [December 10, 2022, 5:12am UTC](https://discourse.julialang.org/t/unexpected-result-from/91499/4 "2022-12-10T05:12:37Z")

</div>

And, if you ever choose to make `SK1` contain more fields:

```julia
Base.:(==)(a::SK1, b::SK1) = 
    all(getfield(a, s) == getfield(b, s) for s ∈ fieldnames(SK1))

```

---

<div class="post-metadata">

**Author:** ![Stephen\_Vavasis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stephen_vavasis/32/3389_2.png) [@Stephen\_Vavasis](https://discourse.julialang.org/u/Stephen_Vavasis)\
**Post date:** [December 10, 2022, 2:17pm UTC](https://discourse.julialang.org/t/unexpected-result-from/91499/5 "2022-12-10T14:17:20Z")

</div>

Sorry, I’m not getting it yet; here are some followup questions.

1. The first response from Oscar\_Smith, which appears to correctly describe the behavior of Julia according to my tests, is inconsistent with the docstring. Here is an excerpt from the docstring:

```julia
help?> ==
   [snip]
For collections, == is generally
  called recursively on all contents, though other properties (like the shape for arrays) may also be taken into
  account.

```

So in other words, the docstring seems to say that `==` should be called on the `nl` field, not `===`.

1. My actual requirement is to use `SK` as a dict key, and I haven’t gotten this to work yet. Below is my attempt to make this work. I was expecting the output of the final four `@show` statements to be 8, 8, 9, 10, but instead I got 7,8,9,10 when I ran the code below, so I am still making some mistake.

Thanks

```julia
abstract type E end
import Base.==
import Base.hash

struct E1 <: E
end

struct E2 <: E
end

struct SK{T <: E}
    nl::Vector{Int}
end

getparamtype(sk::SK{T}) where T = T
==(sk1::SK, sk2::SK) = getparamtype(sk1) === getparamtype(sk2) && sk1.nl == sk2.nl
hash(sk::SK,h::Int) = hash((hash(getparamtype(sk),h),hash(sk.nl,h)),h) 

a = SK{E1}([4,3,5])
b = SK{E1}([4,3,5])
c = SK{E1}([4,3,4])
d = SK{E2}([4,3,5])

@show a == a
@show a == b
@show a == c
@show a == d
@show a != a
@show a != b
@show a != c
@show a != d

u = Dict{SK,Int}()
u[a] = 7
u[b] = 8
u[c] = 9
u[d] = 10
@show u[a]
@show u[b]
@show u[c]
@show u[d]

```

---

<div class="post-metadata">

**Author:** ![albheim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/albheim/32/34660_2.png) [@albheim](https://discourse.julialang.org/u/albheim)\
**Post date:** [December 10, 2022, 3:15pm UTC](https://discourse.julialang.org/t/unexpected-result-from/91499/6 "2022-12-10T15:15:12Z")

</div>

I think you want `hash(sk::SK,h::UInt) = ...`, then your example seems to work for me at least.

---

<div class="post-metadata">

**Author:** ![Stephen\_Vavasis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stephen_vavasis/32/3389_2.png) [@Stephen\_Vavasis](https://discourse.julialang.org/u/Stephen_Vavasis)\
**Post date:** [December 10, 2022, 3:36pm UTC](https://discourse.julialang.org/t/unexpected-result-from/91499/7 "2022-12-10T15:36:38Z")

</div>

Thanks! Changing `Int` to `UInt` indeed fixed the problem with setting up a `Dict`, which was my main issue.

Regarding my other question: is the docstring for `==` incorrect or am I misunderstanding it?

---

<div class="post-metadata">

**Author:** ![albheim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/albheim/32/34660_2.png) [@albheim](https://discourse.julialang.org/u/albheim)\
**Post date:** [December 10, 2022, 4:08pm UTC](https://discourse.julialang.org/t/unexpected-result-from/91499/8 "2022-12-10T16:08:58Z")

</div>

I don’t think it is wrong, but maybe the documentation could be made easier to understand?

Docstring of `==` mentions that it falls back to `===`, which I believe is the case we will hit since even though the struct contains a collection the struct itself is not a collection.

> Generic equality operator. **Falls back to ===.** Should be implemented for all types with a notion of  
> equality, based on the abstract value that an instance represents. For example, all numeric types are  
> compared by numeric value, ignoring type. Strings are compared as sequences of characters, ignoring  
> encoding. **For collections, == is generally called recursively on all contents** , though other  
> properties (like the shape for arrays) may also be taken into account.

Docstring of `===` mentions that immutable objects are compared by bit level contents (this is your struct) and immutable objects by pointers (this is the Vector inside your struct). So I think since the contents of you struct is mutable it will not be stored “inside” your struct, but your struct rather has a pointer to where on the heap those values are, resulting in the pointer being compared by default.

> Determine whether x and y are identical, in the sense that no program could distinguish them. First  
> the types of x and y are compared. If those are identical, mutable objects are compared by address in  
> memory and immutable objects (such as numbers) are compared by contents at the bit level. This  
> function is sometimes called “egal”. It always returns a Bool value.

---

<div class="post-metadata">

**Author:** ![sgaure](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sgaure/32/14779_2.png) [@sgaure](https://discourse.julialang.org/u/sgaure)\
**Post date:** [December 10, 2022, 4:11pm UTC](https://discourse.julialang.org/t/unexpected-result-from/91499/9 "2022-12-10T16:11:28Z")

</div>

There’s an issue scheduled for 2.0 about this.

[https://github.com/JuliaLang/julia/issues/4648](https://github.com/JuliaLang/julia/issues/4648)
