3.11 — Checkpoint: the tip calculator brain
The Phase 3 finale — and it works like real software does. The commission: a tip calculator brain. Dinner cost 1200, the service deserves 10%, four friends are splitting. What does each person pay?
You could write one big function that does everything. Professionals don’t. They build small pure functions and compose them — each one returning its answer so the next can build on it. This is why lesson 3.3 was so insistent about return over console.log: a returned value can feed another function; printed text can’t feed anything. Today that investment pays out in full.
function tipAmount(bill, percent) {
return bill * percent / 100;
}
function totalWithTip(bill, percent) {
return bill + tipAmount(bill, percent);
}
function perPerson(bill, percent, people) {
return totalWithTip(bill, percent) / people;
}
console.log(perPerson(1200, 10, 4));Three definitions, each tiny, each PURE (3.10): inputs through parameters, answers through return, no printing inside. Notice the dependencies: totalWithTip calls tipAmount; perPerson calls totalWithTip. A brain made of three cells.
The deeper story, with the real names for things — this part is what turns “I saw it” into “I can explain it.”
What you just used is called function composition: building bigger behavior by feeding one function’s return value into another. It only works because every piece returns (3.3) and every piece is pure (3.10) — no hidden state, so the only thing connecting them is visible values. When you read professional code, this is most of what you’ll see: small verbs, composed.
💼 On the job — your career quietly begins here: pure, composed functions are exactly what unit tests are written against. expect(tipAmount(1200, 10)).toBe(120) — one line, no setup, no browser, no server. In Phase 10 you write exactly that with Vitest. The functions you wrote today would pass unchanged. You didn’t just finish functions; you built your first testable unit.
Phase 3, complete: machines → parameters → return → functions-as-values → scope → the call stack → closures → callbacks → recursion → purity → composition. Every later phase spends this vocabulary. Next stop, Phase 4: what happens when data comes in groups.
⌨️ part 1 — the smallest brain cell
Start the commission with the smallest piece: a pure function that computes a tip. Nothing printed inside — it RETURNS.
requirements:
- A function named
tipAmountwith two parameters:bill, thenpercent. - It RETURNS bill × percent ÷ 100 — pure: no printing, no outside variables.
- Prove it: print
tipAmount(1200, 10).
when you press RUN, the console must show exactly:
⌨️ part 2 — machines feeding machines
Now the composition: two more pure functions, each one CALLING the previous one and building on its returned value. tipAmount is already in the editor.
requirements:
- A function named
totalWithTip(parameters:bill,percent) that returns the bill PLUS the tip — and it must get the tip by callingtipAmount, not by re-doing the math. - A function named
perPerson(parameters:bill,percent,people) that returns the total split evenly — by callingtotalWithTip. - The grand finale: print
perPerson(1200, 10, 4).
when you press RUN, the console must show exactly:
✏️ Quick check 1
Type what tipAmount(600, 10) returns:
✏️ Quick check 2
Composition only works because these functions ___ their answers instead of printing them. Type the keyword.
✏️ Quick check 3
Compose in your head: type what perPerson(1000, 20, 2) returns:
🗣️ Now teach it back
The Phase 3 graduation speech: explain to a friend how the tip calculator works as three composed pure functions — and why building it that way beats one big function.
Write it as if your friend is sitting next to you. Saved to your journal — future-you will use these notes to teach others.