Skip to content
Part IA Michaelmas Term

Private References and Bank Accounts

Encapsulation via closures

OCaml references are more flexible than those in conventional languages. By capturing a reference in a closure, we can create private, persistent state - analogous to objects in OOP.

makeAccount

exception TooMuch of int

let makeAccount initBalance =
  let balance = ref initBalance in
  let withdraw amt =
    if amt > !balance then
      raise (TooMuch (amt - !balance))
    else begin
      balance := !balance - amt;
      !balance
    end
  in
  withdraw
(* val makeAccount : int -> int -> int = <fun> *)

Key points:

  • balance is a private reference created inside makeAccount.
  • withdraw is the only function with access to balance - it is captured in a closure.
  • The balance cannot be modified except by calling withdraw.
  • An exception TooMuch prevents overdrafts; the amount by which the withdrawal exceeds the balance is carried in the exception.
  • Deposits are withdrawals of a negative amount.

The begin/end block

The syntax begin ... end is equivalent to ( ... ) - it groups expressions into a single expression. In withdraw, it sequences the assignment and the return of the new balance:

begin
  balance := !balance - amt;
  !balance
end

Two independent accounts

let student = makeAccount 500
let director = makeAccount 4000000

student 5       (* => 495 *)
director 150000 (* => 3850000 *)
student 500     (* raises TooMuch 5 *)

Each call to makeAccount creates a fresh reference cell. The two accounts are completely independent. Neither account holder can access the other’s balance - the encapsulation is enforced by the language, not by convention.

Analogy to OOP

ConceptIn OOP (e.g. Java)In OCaml
Private stateInstance variablesCaptured ref cells
MethodsObject methodsReturned closure functions
ConstructorClass constructormakeAccount function
Encapsulationprivate keywordLexical scoping

If the returned function is discarded, the reference becomes unreachable and the garbage collector reclaims it - analogous to closing a dormant bank account.

Generalisation

makeAccount could return multiple functions (e.g. withdraw, deposit, statement) that jointly manage shared private references. In OCaml, these would typically be packaged using records, though they are not covered in this course.