Variables in julia are just labels for objects. The variables can always be changed, but that doesn’t change the underlying data. Nothing is being mutated.
When you write
y = y .^ 2
you’re saying “I want to take my label y and change it so that it now labels the result of y .^ 2.” The operation y .^ 2 allocates a whole new vector. The data y used to label is left unchanged.
For example, let’s make a vector y and then say z = y, and then re-bind y. What ends up happening?
julia> let y = [1, 2, 3]
z = y
y = [4, 5, 6]
z
end
3-element Vector{Int64}:
1
2
3
At the end of this, z is no longer labelleing the same data as y.
Mutation is different. When you mutate something, you’re changing the actual data that the label is pointing to. E.g.:
julia> let y = [1, 2, 3]
z = y
y .= [4, 5, 6]
z
end
3-element Vector{Int64}:
4
5
6
In this case, z and y are still labelling the same data, but have both been changed by the mutation.