Cloning from the Master Mould
A pewterer in 1450 didn’t sculpt each goblet from scratch. They carved one master, pressed it into cuttlebone or soapstone, then poured. Every piece came from that template — identical in form, unique only in the small variations that creep in during cooling.
The Self programming language, designed at Xerox PARC in 1987, formalised this as the prototype pattern: instead of defining classes and instantiating them, you create one canonical object and clone it. JavaScript inherited this model wholesale. Every object you create is a clone of something, modified after the fact.
type Goblet = { height: number; engraving: string };
const masterMould: Goblet = { height: 15, engraving: "Guild Mark" };
const cast = (mould: Goblet, custom: Partial<Goblet> = {}): Goblet => ({
...mould,
...custom,
});
const batch = Array.from({ length: 4 }, (_, i) =>
cast(masterMould, { engraving: `Commission #${i + 1}` })
);
console.log(batch);
The spread operator does the work a mould does — it copies the structure, then lets you modify specific details. The master stays intact.
OCaml lacks prototype chains, but functional record updates give you the same semantics with stronger guarantees:
type goblet = { height : float; engraving : string }
let master_mould = { height = 15.0; engraving = "Guild Mark" }
let cast mould updates = { mould with engraving = updates }
let batch = List.init 4 (fun i ->
cast master_mould (Printf.sprintf "Commission #%d" (i + 1)))
let () = List.iter (fun g -> print_endline g.engraving) batch
The with syntax creates a new record, copying all fields from master_mould except the ones you override. Immutable by default — the original never changes, just like a bronze mould that’s been in a foundry for three generations.
Class-based inheritance asks: what kind of thing is this? Prototypes ask: what existing thing is this based on? The second question maps better to how craftspeople actually work. You don’t define an abstract Vessel hierarchy before making your first cup. You make one cup, decide it’s good, and use it as the pattern for the next hundred.
The trade-off shows up in debugging. Prototype chains can get deep and tangled — JavaScript’s Object.getPrototypeOf() sometimes reveals ancestors you didn’t know existed. OCaml’s explicit record copies avoid this, but you lose the runtime flexibility of modifying prototypes after the fact.
I’ve been carving my first cuttlebone mould all afternoon. A simple dish, nothing fancy. If it works, I’ll pour a dozen from the same impression before the bone wears out.