Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does `==` for struct check recursively in Julia ? It seems not

Tags:

struct

julia

There is a behavior I don't understand when checking for equality in Julia concerning "struct" objects. The documentation states : : "For collections, == is generally called recursively on all contents, though other properties (like the shape for arrays) may also be taken into account". Though it seems for structs it is cast to === or something. Here is a minimal working exemple :

As expected :

string1 = String("S")
string2 = String("S")
string1 == string2 

=> returns true

and :

set1 = Set(["S"])
set2 = Set(["S"])
set1 == set2

=> returns true


BUT ! And that is what I don't understand :

struct StringStruct
    f::String
end
stringstruct1 = StringStruct("S")  
stringstruct2 = StringStruct("S")  
stringstruct1 == stringstruct2  

=> returns true

However :

struct SetStruct  
    f::Set{String}  
end
setstruct1 = SetStruct(Set(["S"]))
setstruct2 = SetStruct(Set(["S"]))
setstruct1 == setstruct2 

=> returns false


To me, it looks like ===is tested on the elements of the struct.

So my question is : what is the real behavior of == when tested on structs ? Does it cast == or === ? In case it casts == as the documentation states, what is the point I misunderstand ?

like image 364
GomsqB0T Avatar asked Dec 30 '22 19:12

GomsqB0T


1 Answers

For structs by default == falls back to ===, so e.g.:

setstruct1 == setstruct2

is the same as

setstruct1 === setstruct2

So now we go down to the way how === works. And it is defined as:

Determine whether x and y are identical, in the sense that no program could distinguish them.

(I am leaving out the rest of the definition, as I believe this fist sentence builds a nice mental model).

Now clearly stringstruct1 and stringstruct2 are non-distinguishable. They are immutable and contain strings that are immutable in Julia. In particular they have the same hash value (which is not a definitive test, but is a nice mental model here).

julia> hash(stringstruct1), hash(stringstruct2)
(0x9e0bef39ad32ce56, 0x9e0bef39ad32ce56)

Now setstrict1 and setstruct2 are distinguishable. They store different sets, although at the moment of comparison these sets contain the same elements, but they have different memory locations (so in the future they can be different - in short - they are distinguishable). Note that these structs have different hashes in particular:

julia> hash(setstruct1), hash(setstruct2)
(0xe7d0f90913646f29, 0x3b31ce0af9245c64)

Now notice the following:

julia> s = Set(["S"])
Set{String} with 1 element:
  "S"

julia> ss1 = SetStruct(s)
SetStruct(Set(["S"]))

julia> ss2 = SetStruct(s)
SetStruct(Set(["S"]))

julia> ss1 == ss2
true

julia> ss1 === ss2
true

julia> hash(ss1), hash(ss2)
(0x9127f7b72f753361, 0x9127f7b72f753361)

This time ss1 and ss2 are passing all the tests, as again they are indistinguishable (if you change ss1 then ss2 changes in sync as they hold the same Set).

like image 62
Bogumił Kamiński Avatar answered Feb 16 '23 03:02

Bogumił Kamiński