# Surprising struct equality test

**URL:** <https://discourse.julialang.org/t/surprising-struct-equality-test/4890>\
**Category:** General Usage\
**Tags:** question\
**Created:** [July 17, 2017, 12:24am UTC](https://discourse.julialang.org/t/surprising-struct-equality-test/4890 "2017-07-17T00:24:30Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![e3c6](https://avatars.discourse-cdn.com/v4/letter/e/e79b87/32.png) [@e3c6](https://discourse.julialang.org/u/e3c6)\
**Post date:** [July 17, 2017, 12:24am UTC](https://discourse.julialang.org/t/surprising-struct-equality-test/4890/1 "2017-07-17T00:24:31Z")

</div>

By my understanding of `struct`s, they should be compared by value by default. So what is going here??

```julia
struct T
    name::String
end

T("hello") == T("hello")

```

returns `false`!

---

<div class="post-metadata">

**Author:** ![cstjean](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cstjean/32/1444_2.png) [@cstjean](https://discourse.julialang.org/u/cstjean)\
**Post date:** [July 17, 2017, 12:30am UTC](https://discourse.julialang.org/t/surprising-struct-equality-test/4890/2 "2017-07-17T00:30:53Z")

</div>

The fields of a struct are compared using `===` (object identity). `"hello" === "hello"` is false. But you’re not alone in finding the behaviour counterintuitive:

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

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [July 17, 2017, 12:30am UTC](https://discourse.julialang.org/t/surprising-struct-equality-test/4890/3 "2017-07-17T00:30:55Z")

</div>

This is because

```julia
julia> "hello" === "hello"
false

```

Mutable members compares through object identity by default.

---

<div class="post-metadata">

**Author:** ![e3c6](https://avatars.discourse-cdn.com/v4/letter/e/e79b87/32.png) [@e3c6](https://discourse.julialang.org/u/e3c6)\
**Post date:** [July 17, 2017, 8:41am UTC](https://discourse.julialang.org/t/surprising-struct-equality-test/4890/4 "2017-07-17T08:41:58Z")

</div>

Is there a way to modify this behavior for my struct? Can I “redefine” equality somehow?

---

<div class="post-metadata">

**Author:** ![e3c6](https://avatars.discourse-cdn.com/v4/letter/e/e79b87/32.png) [@e3c6](https://discourse.julialang.org/u/e3c6)\
**Post date:** [July 17, 2017, 8:50am UTC](https://discourse.julialang.org/t/surprising-struct-equality-test/4890/5 "2017-07-17T08:50:22Z")

</div>

Hmmm, I am confused. Why isn’t `"hello" === "hello"`? Why strings don’t behave like values?

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [July 17, 2017, 8:50am UTC](https://discourse.julialang.org/t/surprising-struct-equality-test/4890/6 "2017-07-17T08:50:34Z")

</div>

You can redefine `Base.:(==)`, but it may break some implicit assumptions in existing code, also, you need to define hashing. For the moment, you are better off defining your own equality operator. I posted [an example](https://discourse.julialang.org/t/what-general-purpose-commands-do-you-usually-end-up-adding-to-your-projects/4889) in a parallel topic.

---

<div class="post-metadata">

**Author:** ![e3c6](https://avatars.discourse-cdn.com/v4/letter/e/e79b87/32.png) [@e3c6](https://discourse.julialang.org/u/e3c6)\
**Post date:** [July 17, 2017, 8:53am UTC](https://discourse.julialang.org/t/surprising-struct-equality-test/4890/7 "2017-07-17T08:53:05Z")

</div>

Thanks. I did this:

```julia
Base.:(==)(x::T, y::T) = x.name == y.name

```

Why do you say that could “break some implicit assumptions in existing code”?  
And you think I have to define hashing in this simple example (my type is literally this simple)? How?  
Thanks!

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [July 17, 2017, 9:08am UTC](https://discourse.julialang.org/t/surprising-struct-equality-test/4890/8 "2017-07-17T09:08:42Z")

</div>

A function could rely on existing behavior of `==`. If you change that, you could break code.

> [@e3c6](#):
>
> `Base.:(==)(x::T, y::T) = x.name == y.name`

Your code is nonsensical, and won’t even compile.

As for hashing, see [the manual](https://docs.julialang.org/en/latest/stdlib/base/#Base.hash). Or as an example,

> **[GitHub - JuliaServices/AutoHashEquals.jl: A Julia macro to add == and hash()...](https://github.com/JuliaServices/AutoHashEquals.jl)**
>
> A Julia macro to add == and hash() to composite types. - GitHub - JuliaServices/AutoHashEquals.jl: A Julia macro to add == and hash() to composite types.

---

<div class="post-metadata">

**Author:** ![e3c6](https://avatars.discourse-cdn.com/v4/letter/e/e79b87/32.png) [@e3c6](https://discourse.julialang.org/u/e3c6)\
**Post date:** [July 17, 2017, 9:11am UTC](https://discourse.julialang.org/t/surprising-struct-equality-test/4890/9 "2017-07-17T09:11:33Z")

</div>

What do you mean it won’t compile? I have it right here ant it works. Do you get an error??

Note that I am defining `==` only for my type `T` … I don’t see the danger, maybe I am missing something?

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [July 17, 2017, 9:15am UTC](https://discourse.julialang.org/t/surprising-struct-equality-test/4890/11 "2017-07-17T09:15:20Z")

</div>

> [@e3c6](#):
>
> I have it right here ant it works. Do you get an error??

I thought `T` was a type parameter, which should have required a `where T`. If it is a concrete type, which has a field `name`, then it should work.

---

<div class="post-metadata">

**Author:** ![e3c6](https://avatars.discourse-cdn.com/v4/letter/e/e79b87/32.png) [@e3c6](https://discourse.julialang.org/u/e3c6)\
**Post date:** [July 17, 2017, 9:19am UTC](https://discourse.julialang.org/t/surprising-struct-equality-test/4890/12 "2017-07-17T09:19:25Z")

</div>

Ah yes, sorry. I was using the `T` I defined in the first post.

---

<div class="post-metadata">

**Author:** ![e3c6](https://avatars.discourse-cdn.com/v4/letter/e/e79b87/32.png) [@e3c6](https://discourse.julialang.org/u/e3c6)\
**Post date:** [July 17, 2017, 10:01am UTC](https://discourse.julialang.org/t/surprising-struct-equality-test/4890/13 "2017-07-17T10:01:43Z")

</div>

This is very unintuitive:

```julia
struct T1 s::String end
Base.:(==)(x::T1, y::T1) = x.s == y.s

struct T2 i::Int end
struct P x::T1 end
struct Q x::T2 end

@show T1("hola") == T1("hola"); # true
@show P(T1("hola")) == P(T1("hola")); # false (!)
@show Q(T2(1)) == Q(T2(1)); # true (wtf)

```

How can I fix this? I want my `T1` to behave like a true value. Overloading `==` on `T1` is not enough, as you can see from this example. I would have to re-define `==` on `P` as well (and all composite types that contain `T1`, which is impractical). And overloading `===` of `T1` seems to be forbidden (I get an error).

@Tamas_Papp @cstjean @yuyichao (help me 🙂 )

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [July 17, 2017, 10:26am UTC](https://discourse.julialang.org/t/surprising-struct-equality-test/4890/14 "2017-07-17T10:26:32Z")

</div>

The answer is in the very first response you got. Also, note that pinging people for no good reason is considered impolite.

---

<div class="post-metadata">

**Author:** ![e3c6](https://avatars.discourse-cdn.com/v4/letter/e/e79b87/32.png) [@e3c6](https://discourse.julialang.org/u/e3c6)\
**Post date:** [July 17, 2017, 10:31am UTC](https://discourse.julialang.org/t/surprising-struct-equality-test/4890/15 "2017-07-17T10:31:17Z")

</div>

Sorry, but I do not see how that fixes the problem? I mean a workaround to make `T1` behave as a true value type, in spite of the string field. Care to explain?

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [July 17, 2017, 11:10am UTC](https://discourse.julialang.org/t/surprising-struct-equality-test/4890/16 "2017-07-17T11:10:58Z")

</div>

Strings are for implementation reasons defined as a mutable struct and therefore use object equality for `===`.

---

<div class="post-metadata">

**Author:** ![e3c6](https://avatars.discourse-cdn.com/v4/letter/e/e79b87/32.png) [@e3c6](https://discourse.julialang.org/u/e3c6)\
**Post date:** [June 1, 2018, 8:58am UTC](https://discourse.julialang.org/t/surprising-struct-equality-test/4890/17 "2018-06-01T08:58:22Z")

</div>

Are ther eplans to fix this issue for v1.0?

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [June 3, 2018, 4:44pm UTC](https://discourse.julialang.org/t/surprising-struct-equality-test/4890/18 "2018-06-03T16:44:45Z")

</div>

0.7:

```julia
julia> "hello" === "hello"
true

julia> struct T
           name::String
       end

julia> T("hello") == T("hello")
true

```

---

<div class="post-metadata">

**Author:** ![piever](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/piever/32/1815_2.png) [@piever](https://discourse.julialang.org/u/piever)\
**Post date:** [June 3, 2018, 4:56pm UTC](https://discourse.julialang.org/t/surprising-struct-equality-test/4890/19 "2018-06-03T16:56:55Z")

</div>

To make sure I understand this correctly (I’ve already got confused by this issue in the past): the counter-intuitive `T("Hello") != T("Hello")` was fixed, but not by making `==` call the various fields recursively (meaning `a == b` iff `a.f == b.f` for every field). Instead what changed is that now the same string literals are `===`?

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [June 3, 2018, 5:04pm UTC](https://discourse.julialang.org/t/surprising-struct-equality-test/4890/20 "2018-06-03T17:04:09Z")

</div>

Yes.
