← Back to the lab

Problem 6: ref and String.iter

For count_letter.

A mutable counter

ref 0 creates a mutable cell holding the integer 0. !r reads the current value; r := v writes a new one; incr r is shorthand for r := !r + 1.

let counter = ref 0
let () = incr counter
let () = incr counter
let _ = !counter   (* = 2 *)

A ref is the escape hatch for the rare case where threading a value through as a function argument (the way List.fold_left's accumulator does) would be more awkward than just mutating a cell in place.

Walking every character of a string

String.iter f s calls f once for every character of s, left to right, purely for the side effect -- it returns unit, nothing is built up and handed back.

let () = String.iter print_char "hi"   (* prints "hi" *)

Combine the two: a ref counter, incremented once per character that matches, counts occurrences.

let count_vowels s =
  let n = ref 0 in
  String.iter (fun c -> if String.contains "aeiou" c then incr n) s;
  !n

Why not recursion here?

Nothing is wrong with a recursive version over String.to_seq s |> List.of_seq, but String.iter already says "do something for each character" directly, and a single mutable counter is the simplest possible "something."