Skip to content
Imperative OCaml: refs, arrays, loops
step 1/7

Reading — step 1 of 7

Learn

~3 min readHigher-Order, Exceptions, Imperative

OCaml is functional FIRST but supports imperative style when needed. Mutable references, arrays, and for/while loops are all available — use sparingly, where they fit.

References — single-cell mutation

let counter = ref 0
incr counter                     (* counter := !counter + 1 *)
incr counter
incr counter
Printf.printf "%d\n" !counter   (* 3 — dereference with ! *)
  • ref initial_value — create a mutable cell
  • !r — dereference (read the contents)
  • r := new_value — assign
  • incr r / decr r — increment / decrement int refs

Refs hold a single value of any type. Useful for counters, accumulators in imperative loops, or implementing stateful APIs.

Arrays — fixed-size mutable

let arr = [| 1; 2; 3; 4; 5 |]    (* | brackets *)
arr.(0)                            (* 1 — read *)
arr.(2) <- 99                       (* set *)
Array.length arr                   (* 5 *)
Array.iter print_int arr           (* 1299145 *)
Array.map (fun x -> x * 2) arr     (* [|2; 4; 198; 8; 10|] *)
  • [| ... |] — array literal
  • arr.(i) — index access (parens around index, NOT brackets)
  • arr.(i) <- v — assignment

Arrays are MUTABLE and FIXED-SIZE. Different from lists (immutable, linked).

When to use arrays vs lists

  • List — immutable, easy to prepend, pattern-match, recurse over
  • Array — fixed size known up front, fast random access, in-place updates

Most OCaml code uses lists. Arrays for performance-critical numeric or random-access work.

for and while loops

for i = 0 to 4 do
    Printf.printf "%d " i
done
(* 0 1 2 3 4 *)

for i = 4 downto 0 do
    Printf.printf "%d " i
done
(* 4 3 2 1 0 *)

let i = ref 0 in
while !i < 5 do
    Printf.printf "%d " !i;
    incr i
done

for loops are inclusive: for i = 1 to 10 iterates 1..=10. to for ascending; downto for descending. while for general loops with mutable conditions.

The loop body must have type unit. Use ; to sequence multiple statements.

Mutable record fields

type counter = { mutable count : int }

let c = { count = 0 }
c.count <- c.count + 1
c.count <- c.count + 1
Printf.printf "%d\n" c.count   (* 2 *)

mutable field allows in-place modification with <-. Other fields stay immutable.

Hashtbl — mutable hash maps

let tbl = Hashtbl.create 16
Hashtbl.add tbl "alice" 30
Hashtbl.add tbl "bob" 25
Hashtbl.find tbl "alice"           (* 30 *)
Hashtbl.find_opt tbl "missing"     (* None *)
Hashtbl.mem tbl "alice"            (* true *)
Hashtbl.remove tbl "bob"
Hashtbl.iter (fun k v -> Printf.printf "%s:%d " k v) tbl

Mutable in-place hash table. Useful for caches, frequency counts, set-like usage.

For immutable maps, use the Map module (functor-based, slightly more ceremonial).

Sequence operators — ; and let-binding

let () =
    print_string "hello ";
    print_string "world";
    print_newline ()

; separates statements (each must have type unit). For binding values, use let:

let name = read_line () in
let age = int_of_string (read_line ()) in
Printf.printf "%s is %d\n" name age

When to mix functional and imperative

Yes:

  • Performance-critical inner loops (mutable accumulator)
  • Hash tables for fast lookup
  • Implementing stateful APIs (caches, generators)

No:

  • Default coding style
  • Public API surface (return values, not mutate parameters)
  • When pattern matching + recursion is clearer

Functional code is the OCaml default; reach for imperative where it pays.

Common mistakes

  • Forgetting ! to read a ref — using r directly gives the ref, not the contents.
  • Using [] for array access — OCaml uses arr.(i), not arr.[i] (brackets are for STRINGS).
  • Forgetting ; between statements — sequencing operator.
  • Mixing mutable refs with functional flow — don't pass ref-holding records around as if immutable.
  • Hashtbl.add when you meant replaceadd keeps duplicate keys (with stack semantics). Use Hashtbl.replace to overwrite.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…