# Struct equality seems weird inside Sets

**URL:** <https://discourse.julialang.org/t/struct-equality-seems-weird-inside-sets/51283>\
**Category:** General Usage\
**Tags:** set, struct, isequal\
**Created:** [December 5, 2020, 12:09am UTC](https://discourse.julialang.org/t/struct-equality-seems-weird-inside-sets/51283 "2020-12-05T00:09:09Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![bsuwal](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bsuwal/32/19577_2.png) [@bsuwal](https://discourse.julialang.org/u/bsuwal)\
**Post date:** [December 5, 2020, 12:09am UTC](https://discourse.julialang.org/t/struct-equality-seems-weird-inside-sets/51283/1 "2020-12-05T00:09:09Z")

</div>

![Screen Shot 2020-12-04 at 7.02.36 PM](https://global.discourse-cdn.com/julialang/original/3X/4/0/40aa36e084158a5917ffb5b8adbcc4a8899834ae.png)

Can someone help me understand this behavior?

So I define a struct. To define what equality means for the struct, I define the `==` function for the struct, and also a `hash() ` function.

Note the `println()` statements in the definition.

It seems that for the Set equality case, when the structs are not the same the program isn’t entering the `==` function. Why?

Code:

```julia
mutable struct ForbiddenPair
    comp₁::Int
    comp₂::Int
end

function Base.:(==)(fp_1::ForbiddenPair, fp_2::ForbiddenPair)
    comp1s = (fp_1.comp₁ == fp_2.comp₁)
    comp2s = (fp_1.comp₂ == fp_2.comp₂)
    println("Comp 1s: ", comp1s)
    println("Comp 2s: ", comp2s)
    comp1s && comp2s
end

Base.hash(fp::ForbiddenPair, h::UInt) = hash(fp.comp₁, hash(fp.comp₂, hash(:ForbiddenPair, h)))

a = ForbiddenPair(1, 2)
b = ForbiddenPair(1, 2)
c = ForbiddenPair(2, 2)

println(a == b, " ", hash(a) == hash(b))
println()
println(a == c, " ", hash(a) == hash(c))

a = Set([ForbiddenPair(1, 2)])
b = Set([ForbiddenPair(1, 2)])
c = Set([ForbiddenPair(2, 2)])

println(a == b, " ", hash(a) == hash(b))
println()
println(a == c, " ", hash(a) == hash(c))

```

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [December 5, 2020, 12:16am UTC](https://discourse.julialang.org/t/struct-equality-seems-weird-inside-sets/51283/2 "2020-12-05T00:16:07Z")

</div>

Could you please post your actual code instead of a screenshot? See [PSA: how to quote code with backticks](https://discourse.julialang.org/t/psa-how-to-quote-code-with-backticks/7530) for some helpful tips on formatting code on Discourse. Screenshots make it harder to help you because there’s no way to copy your code to test it out locally.

---

<div class="post-metadata">

**Author:** ![bsuwal](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bsuwal/32/19577_2.png) [@bsuwal](https://discourse.julialang.org/u/bsuwal)\
**Post date:** [December 5, 2020, 12:25am UTC](https://discourse.julialang.org/t/struct-equality-seems-weird-inside-sets/51283/3 "2020-12-05T00:25:09Z")

</div>

Woops thanks for letting me know the etiquette, just made the edit!

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [December 5, 2020, 12:27am UTC](https://discourse.julialang.org/t/struct-equality-seems-weird-inside-sets/51283/4 "2020-12-05T00:27:14Z")

</div>

Thanks!

I think all that’s going on here is that the hash for the entry in set `c` is different than the hash of the entry in set `a`, so the equality check can be performed without needing to use `==` at all. After all, that’s kind of the point of a hash table: most of the time we can skip equality checks when there is no hash collision.

---

<div class="post-metadata">

**Author:** ![bsuwal](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bsuwal/32/19577_2.png) [@bsuwal](https://discourse.julialang.org/u/bsuwal)\
**Post date:** [December 5, 2020, 12:28am UTC](https://discourse.julialang.org/t/struct-equality-seems-weird-inside-sets/51283/5 "2020-12-05T00:28:36Z")

</div>

Thank you, that makes a lot of sense!

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [December 5, 2020, 12:32am UTC](https://discourse.julialang.org/t/struct-equality-seems-weird-inside-sets/51283/6 "2020-12-05T00:32:06Z")

</div>

BTW, if you want to prove this for yourself, you can use the debugger to step into the actual calls and look what’s going on. To do that, you’ll need to install `Debugger.jl` via:

```julia
pkg> add Debugger

```

and then do

```julia
using Debugger
@enter a == c

```

Try `s` to step into the next call, `so` to step out of a call, and `o` to open the given function in a text editor. The fact that Julia is mostly implemented in Julia means that you can go all the way into the guts of how `Set` equality works without having to switch languages or tools.

---

<div class="post-metadata">

**Author:** ![malacroi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/malacroi/32/19745_2.png) [@malacroi](https://discourse.julialang.org/u/malacroi)\
**Post date:** [December 5, 2020, 12:52am UTC](https://discourse.julialang.org/t/struct-equality-seems-weird-inside-sets/51283/7 "2020-12-05T00:52:53Z")

</div>

You can see how the hash comes into play in `Set` comparisons by purposefully defining a bad hash function that leads to collisions. Try redoing the test, for example with

```julia
Base.hash(fp::ForbiddenPair, h::UInt) = hash(fp.comp₂)

```

If you make this change, then `hash(ForbiddenPair(1,2))==hash(ForbiddenPair(2,2)`, so the set comparison needs to call `==` on the elements to figure out if they’re the same, and your extra lines will print.
