Comparing Mutable Structs


#1

dear wizards—is this intended behavior?

julia> mutable struct S; x::Int; end#struct##

julia> v= [ S(1), S(2) ]
2-element Array{S,1}:
 S(1)
 S(2)

julia> v==deepcopy(v)   ## only when v is mutable
false

julia> v==copy(v)
true

if so, how do I check that a deepcopy() result has identical content to its original?

advice appreciated.

regards,

/iaw


#2

This is fully intended. You should note that v = S(1); v != deepcopy(v) and S(1) != S(1) so comparing the object with != won’t be useful.

By definition you can check the serialization being the same, though you should really specify what do you actually want to do. Writing test for deepcopy?


#3

uggh. I should have started simpler. My premise was wrong. I have a worse lack of understanding mutables vs const than I thought. It does way more than just make contents unchangeable.

julia> mutable struct S; x::Int; end#struct##

julia S(1) == S(1)
false

I had known that S(1) === S(1), because the left object is distinguishable from the right object. The L creates an object different from the R, so assigning to one would not be the same as assigning to the other.

So what is S(1) == S(1) actually testing that is different from S(1) === S(2) with mutable structs?

julia> struct R; x::Int; end#struct##

julia R(1) == R(1)
true

Similar question here for immutable. Again, == and === seem to do the same thing.

It is a virtue when programming languages give the naively expected results…


#4

By default, nothing. You can check this yourself. Just do:

julia> mutable struct S; end

julia> @edit S() == S()

which shows that the default implementation is:

## generic comparison ##

==(x, y) = x === y

The difference is that you can overload == to mean whatever you want for a particular type.

There’s no way for Julia to know exactly what == equality means to you for some new type, so by default it does the most conservative thing and only declares two mutable structs as equal if they are truly indistinguishable.


#5

And note that if you do overload Base.:(==), you should also overload Base.hash (except you should overload the two-argument version, as noted in https://docs.julialang.org/en/stable/stdlib/base/#Base.hash); see https://docs.julialang.org/en/stable/stdlib/base/#Base.isequal-Tuple{Any,Any}.


#6

Related reading: https://github.com/JuliaLang/julia/issues/4648


#7

even C knows this for structs! :wink:


#8

Are you sure about that?


#9

I stand corrected.

It just seems strange that if I can write a=b, I should be able to write a==b and (except for NaN type cases) receive true.

regards,

/iaw


#10

Note that this IS actually the case in julia.


#11

this is what you get if you allow idiots onto discourse forums…

PS: fortunately, my turning red is not visible over the net.