Lab
Singleton
type Admission = { allowed: boolean; remaining: number };
type Budget = { tryTake(): Admission };
// A budget of attempts, spent one at a time.
function createBudget(limit: number): Budget {
let remaining = limit;
return {
tryTake() {
const allowed = remaining > 0;
if (allowed) remaining -= 1;
return { allowed, remaining };
},
};
}
// The access point: created on the first call, returned ever after.
let appBudget: Budget | undefined;
function getAppBudget(): Budget {
appBudget ??= createBudget(3);
return appBudget;
}
// Two callers, one allowance: each asks the access point.
function search(): Admission {
const budget = getAppBudget();
return budget.tryTake();
}
function exportResults(): Admission {
const budget = getAppBudget();
return budget.tryTake();
}
const first = search();
const second = search();
const third = exportResults();
const fourth = exportResults();
const show = (name: string, a: Admission) =>
console.log(`${name}: allowed=${a.allowed} remaining=${a.remaining}`);
show('search', first);
show('search', second);
show('export', third);
show('export', fourth);
Searchasks the access point
Exportasks the access point
Last observed count—Captured variable in TypeScript; budget field in Go/Rust. A copied wrapper need not copy
its state.
Count not observed yet
Recorded objects appear as the program reaches them. No instance has been identified at this stop.
Identity badges name recorded objects, not addresses. Bindings beside one badge reach that same object. Missing or opaque state stays —; Recorded objects exposes the full snapshot. Closure and native wrapper internals may hide links.