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.
isequalThe 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