julia> isequal(diagm(ones(3)), I)
true
julia> isequal(diagm(ones(4)), I)
true
julia> hash(I)
0x6bd2535d045989b2
julia> hash(diagm(ones(4)))
0x6ba2635b5ca237d8
julia> hash(diagm(ones(3)))
0xf728e5a95d43274d
This is because isequal on UniformScaling is not defined and dispatches to the generic method
julia> @which isequal(diagm(ones(3)), I)
isequal(x, y) in Base at operators.jl:123
which calls ==:
It seems isequal on UniformScaling has to be defined manually.
A more fundamental solution may be to define isequal in terms of the identity === by default. It seems brittle to define a function with strict semantics (isequal) in terms of the one with weaker semantics (==). (Though this is probably impossible to do within 1.x.)
The fundamental issue is that == is non-transitive in the presence of I which is a bad situation:
julia> I(3) == I == I(4)
true
julia> I(3) == I(4)
false
The best solution is unclear, however. It seems that it's either this or make I(n) == I false.
I want to slate this for fixing in 1.6 since this is the only example of equality being non-transitive that I'm aware of.
Triage agrees that I(n) == I should not be true, so now we "just" need a PR to change this.
Once there's a PR, we'll need a PkgEval run.
While I think it's probably right to change the behavior here, the discussion reminds me that there are some more general challenges associated with the "x==y implies hash(x) == hash(y)" orthodoxy https://github.com/JuliaParallel/DistributedArrays.jl/issues/4#issuecomment-89590255
Most helpful comment
Triage agrees that
I(n) == Ishould not be true, so now we "just" need a PR to change this.