Surprising struct equality test

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

struct T

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

returns false!


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


This is because

julia> "hello" === "hello"

Mutable members compares through object identity by default.

1 Like

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


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

1 Like

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 in a parallel topic.


Thanks. I did this:

Base.:(==)(x::T, y::T) = ==

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?

1 Like

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

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

As for hashing, see the manual. Or as an example,


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?

1 Like

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.

1 Like

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

This is very unintuitive:

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 :slight_smile: )

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

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?

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

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


julia> "hello" === "hello"

julia> struct T

julia> T("hello") == T("hello")
1 Like

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 ===?