There are three equality operators: ==
, ===
, and isequal
. (The last is not really an operator, but it is a function and all operators are functions.)
==
==
is value equality. It returns true
when two objects represent, in their present state, the same value.
For instance, it is obvious that
julia> 1 == 1
true
but furthermore
julia> 1 == 1.0
true
julia> 1 == 1.0 + 0.0im
true
julia> 1 == 1//1
true
The right hand sides of each equality above are of a different type, but they still represent the same value.
For mutable objects, like arrays, ==
compares their present value.
julia> A = [1, 2, 3]
3-element Array{Int64,1}:
1
2
3
julia> B = [1, 2, 3]
3-element Array{Int64,1}:
1
2
3
julia> C = [1, 3, 2]
3-element Array{Int64,1}:
1
3
2
julia> A == B
true
julia> A == C
false
julia> A[2], A[3] = A[3], A[2] # swap 2nd and 3rd elements of A
(3,2)
julia> A
3-element Array{Int64,1}:
1
3
2
julia> A == B
false
julia> A == C
true
Most of the time, ==
is the right choice.
===
===
is a far stricter operation than ==
. Instead of value equality, it measures egality. Two objects are egal if they cannot be distinguished from each other by the program itself. Thus we have
julia> 1 === 1
true
as there is no way to tell a 1
apart from another 1
. But
julia> 1 === 1.0
false
because although 1
and 1.0
are the same value, they are of different types, and so the program can tell them apart.
Furthermore,
julia> A = [1, 2, 3]
3-element Array{Int64,1}:
1
2
3
julia> B = [1, 2, 3]
3-element Array{Int64,1}:
1
2
3
julia> A === B
false
julia> A === A
true
which may at first seem surprising! How could the program distinguish between the two vectors A
and B
? Because vectors are mutable, it could modify A
, and then it would behave differently from B
. But no matter how it modifies A
, A
will always behave the same as A
itself. So A
is egal to A
, but not egal to B
.
Continuing along this vein, observe
julia> C = A
3-element Array{Int64,1}:
1
2
3
julia> A === C
true
By assigning A
to C
, we say that C
has aliased A
. That is, it has become just another name for A
. Any modifications done to A
will be observed by C
also. Therefore, there is no way to tell the difference between A
and C
, so they are egal.
isequal
The difference between ==
and isequal
is very subtle. The biggest difference is in how floating point numbers are handled:
julia> NaN == NaN
false
This possibly surprising result is defined by the IEEE standard for floating point types (IEEE-754). But this is not useful in some cases, such as sorting. isequal
is provided for those cases:
julia> isequal(NaN, NaN)
true
On the flip side of the spectrum, ==
treats IEEE negative zero and positive zero as the same value (also as specified by IEEE-754). These values have distinct representations in memory, however.
julia> 0.0
0.0
julia> -0.0
-0.0
julia> 0.0 == -0.0
true
Again for sorting purposes, isequal
distinguishes between them.
julia> isequal(0.0, -0.0)
false