When == is passed arguments of different type

just wondering about the design choice where, for example,
julia> Int8(1)==Int64(1)
true
julia> typeof(Int8(1))==typeof(Int64(1))
false

why is it that way ? or why was that choice made ? as opposed to, for example,
julia> Int8(1)==Int64(1)
false

p.s. long time julia user first time poster; I appreciate everyone contributing to the design

I would think that that’s because the integer 1 is exactly the same value whether it is stored as an 8-bit of 64-bit integer? So the question is whether the exact same number can be represented with the numerical type. Compare to e.g.:

julia> Float64(1) == Float32(1)
true

julia> Float64(0.3) == Float32(0.3)
false
6 Likes

Also I would add there is === for a comparison involving the type altogether.

2 Likes

The basic gist is in the == docs, emphasis mine:

Generic equality operator. Falls back to ===. Should be implemented for all types with a notion of equality, based on the abstract value that an instance represents. For example, all numeric types are compared by numeric value, ignoring type.

This isn’t a trivial matter, and it really cuts to the core of what makes Julia’s generic functions (and multiple dispatch) work. Doing this consistently is quite the feat, especially as it has impacts on other comparisons and hashing… and it needs to play nicely with promotion and wonky floating point semantics and more.

8 Likes

It seems Jeff and Stefan want to get rid of this misfeature in 2.0.

That’s not what the OP was asking about — Int8(1) == 1 == 1.0 == 1/1 is not generally considered a misfeature. That issue is about comparing types that don’t have a meaningful relation, like 1 == Dict("hello"=>[]).

5 Likes

Base.jl has this line:

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

So that means if there is no defined method to compare two values, it falls back to identity comparison. You can check that with methods(==):

julia> methods(==)
# 171 methods for generic function "==":
[1] ==(r::Union{StepRange{T}, StepRangeLen{T, T}}, s::Union{StepRange{T}, StepRangeLen{T, T}}) where T in Base at range.jl:1116
[2] ==(r::T, s::T) where T<:Union{LinRange, StepRangeLen} in Base at range.jl:1113
...
[161] ==(y::Int64, x::Float32) in Base at float.jl:450
[162] ==(y::Int64, x::Float64) in Base at float.jl:450
[163] ==(x::T, y::T) where T<:Number in Base at promotion.jl:477
[164] ==(x::Number, y::Number) in Base at promotion.jl:427
...
[169] ==(x) in Base at operators.jl:1135
[170] ==(w, v::WeakRef) in Base at gcutils.jl:5
[171] ==(x, y) in Base at Base.jl:116