Default ==() for structs doesn't work for struct witth Decimals?

Why does this happen?

using Decimals

struct MyType{T,P}
    x::T
    y::P
end

t1 = MyType{Int64,Int64}(1,2)
t2 = MyType{Int64,Int64}(1,2)
t1 == t2  # true, expected
q1 = MyType{Decimal,Int64}(1,2)
q2 = MyType{Decimal,Int64}(1,2)
q1 == q2  # false, unexpected
q1.x == q2.x  # true, expected

The problem doesn’t seem the comparison of Decimals themselves though, as q1.x == q2.x evaluates to true, as expected.

Is it because isbits(t1) but not isbits(q1)? If so, how is the choice of ==() affected by this? Is there somewhere in the docs where this is explained?

Because == is not explicitly defined on type MyType{T,P} it falls back to:

julia> @less ==(q1,q2)

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

therefor false.
There is no implicit == which compares each part of struct. You have to define this for your types, e.g.:

julia> import Base.==

julia>  ==(a::MyType{T,P},b::MyType{T,P}) where {T,P} = a.x == b.x && a.y == b.y
== (generic function with 175 methods)

julia> ==(q1,q2)
true

I wouldn’t say that it is because isbits(q1) is false. The type Decimal is because of it’s implementation not a isbitstype and because of it’s implementation === is false in equal values but different variables. But this is somehow esoteric so lets just say:

julia> isbitstype(Decimal)
false

so we expect

julia> Decimal(1) === Decimal(1)
false

I don’t hink it’s somewhere explicit in the docs. Perhaps it helps if you look at the types dump:

julia> dump(Decimal(1))
Decimal
  s: Int64 0
  c: BigInt
    alloc: Int32 2
    size: Int32 1
    d: Ptr{UInt64} @0x0000000103fa10a0
  q: Int64 0

julia> dump(1)
Int64 1
2 Likes

Even more general to just omit the type parameters:

Base.:(==)(a::MyType, b::MyType) = a.x == b.x && a.y == b.y
1 Like