The dichotomy between single assignment and variable-name reuse seems to be false. In OCaml, you can just rebind the same variable name again halfway a function body, which will cause a new variable with that name to be bound, having a scope of the rest of the function body. Everybody wins.
Or, you can use explicitly use a reference variable or mutable variable: (# lines are input, - : lines are response)
type egg_carton = { mutable eggs: int }
let my_c = { eggs=12 }
let breakfast carton = carton.eggs <- carton.eggs - 2
# my_c;;
- : egg_carton = {eggs = 12}
# breakfast my_c;;
- : unit = ()
# my_c;;
- : egg_carton = {eggs = 10}
and
type food = Pancakes | Eggs
let eat f = f := None
let short_stack = ref (Some Pancakes)
# short_stack;;
- : food option ref = { contents = Some Pancakes }
# eat short_stack;;
- : unit = ()
# short_stack;;
- : food option ref = {contents = None}
I think the best part here is that OCaml doesn't use = to assign values, it uses a left arrow (<-) for modifying mutable variables and := for updating what value a reference is pointing to.