Several older languages—including Pascal and the Algol languages—will use the := operator for all assignment, on the grounds that assignment is a fundamentally asymmetric operation. In the ML family of languages, there are immutable definitions and mutable reference cells, and different operators for each:
(* multiple bindings, so the inner x shadows the
* outer x---indeed, this code would give you a
* warning about the unused outer x *)
let x = 5 in
let x = 6 in x
(* y is a mutable reference cell being modified *)
let y = ref 5 in
y := 6; y
Haskell makes a distinction between name-binding and name-binding-with-possible-side-effect, but still reserves = to mean signify an immutable definition and not assignment:
-- this defines x to be one more than itself---which
-- causes an infinite loop of additions when x is used
let x = x + 1 in x
-- a different assignment operator is used in a context
-- in which side-effects might occur, and can be
-- interspersed with non-side-effectful bindings:
do { x <- readInt -- does IO
; let y = 1 -- doesn't do IO
; return (x + y)
}