Imperative Programming

ref is just type 'a ref = { mutable contents : 'a }.

16.1 References

ref is just type 'a ref = { mutable contents : 'a }.

let counter = ref 0          (* int ref *)
let () = counter := !counter + 1     (* := assigns, ! dereferences *)
let () = incr counter; decr counter
!counter

16.2 Loops

There is no break/continue — use recursion, exceptions, or Seq instead.

for i = 1 to 5 do Printf.printf "%d " i done
for i = 5 downto 1 do Printf.printf "%d " i done

let i = ref 0 in
while !i < 5 do
  print_int !i;
  incr i
done

16.3 Arrays — fixed-size, mutable, O(1) access

⚠️ Array.make 3 (Array.make 3 0) shares the *same* inner array 3 times — use Array.make_matrix or Array.init.

Bounds-checked: out of range raises Invalid_argument "index out of bounds".

let arr = [| 1; 2; 3; 4; 5 |]
arr.(0)                          (* 1 *)
arr.(0) <- 10
Array.length arr
Array.make 5 0                   (* [|0;0;0;0;0|] *)
Array.init 5 (fun i -> i * i)
Array.map, Array.mapi, Array.iter, Array.iteri, Array.fold_left
Array.to_list, Array.of_list
Array.sort compare arr           (* in place *)
Array.copy, Array.sub, Array.append, Array.concat, Array.blit, Array.fill
Array.exists, Array.for_all, Array.mem, Array.find_opt
Array.make_matrix 3 3 0          (* 2D array *)
Array.split, Array.combine, Array.to_seq

16.4 Float arrays & Bigarray

float array is stored unboxed (flat doubles) — fast numerics.

Float.Array gives an always-flat float array.

Bigarray — large multidimensional numeric arrays, C/Fortran layout, memory-mapping, shared with C.

let m = Bigarray.Array2.create Bigarray.float64 Bigarray.c_layout 100 100
let () = m.{0, 0} <- 1.0

16.5 Dynamic arrays (OCaml 5.2+)

let d = Dynarray.create ()
let () = Dynarray.add_last d 1; Dynarray.add_last d 2
Dynarray.get d 0, Dynarray.length d, Dynarray.pop_last d

16.6 When to go imperative

Mutation is fine when: performance demands it, it's localised (inside a function), or the algorithm is naturally imperative (graph search with visited arrays, dynamic programming). Keep public interfaces pure where practical.

(* Dynamic programming: longest common subsequence *)
let lcs a b =
  let n = String.length a and m = String.length b in
  let dp = Array.make_matrix (n + 1) (m + 1) 0 in
  for i = 1 to n do
    for j = 1 to m do
      dp.(i).(j) <-
        if a.[i-1] = b.[j-1] then dp.(i-1).(j-1) + 1
        else max dp.(i-1).(j) dp.(i).(j-1)
    done
  done;
  dp.(n).(m)