Explain line N
What it does, the case it protects, and the input that breaks without it.
Predict first
Before you read: predict
ExamHall's proctor console applies alerts from the live feed. MR !3350, "simplify the alert loop", deletes one line, if (state.seen.has(alert.id)) continue;, and changes nothing else:
After the merge, five alerts arrive, one for each of five candidates. The feed drops, reconnects and sends its last three alerts again, with the same ids.
What does header show?
// src/console/alert-feed.js (excerpt)export function createConsole() { return { seen: new Set(), tiles: new Map(), flagCount: 0 };} export function applyAlerts(state, batch) { for (const alert of batch) { if (state.seen.has(alert.id)) continue; state.seen.add(alert.id); state.tiles.set(alert.candidateId, alert.kind); state.flagCount += 1; } return state;} export function header(state) { return `${state.tiles.size} flagged candidates · ${state.flagCount} flags`;}The 30-second version
Asked "why is this line here?", give three parts: what it does, the case it protects, and what breaks without it, as one input and the wrong result. Find that case by asking which input makes the line matter, then run both versions on it. Look for the failure where the line's effect is read.
What it does, the case it protects, and the input that breaks without it.
How it works
Step 1 of 10
In the kitchen
- the answer that holds: it holds the boom forward, for running downwind when the wind shifts behind the sail, or the boom swings across the cockpit at head height → what it does, the case it protects, what breaks (step 1)
Analogy: A yacht skipper asking a new crew member why one rope, the boom preventer, is rigged
| On the yacht | In the code |
|---|---|
| "it runs from the boom end to a cleat at the bow" describes the rope and explains nothing | a paraphrase of the syntax (step 2) |
| the answer that holds: it holds the boom forward, for running downwind when the wind shifts behind the sail, or the boom swings across the cockpit at head height | what it does, the case it protects, what breaks (step 1) |
| on a calm beam reach, sailing without it changes nothing | the line matters on one input only (step 3) |
| a test on that heading proves nothing; the skipper tries the downwind run | run the removal on the case it protects (step 4) |
| the harm lands in the cockpit, not on the rope | look where the effect is read (step 5) |
| a line kept rigged though no heading needs it is called spare, not explained | dead or defensive (step 10) |
In real terms: a line earns its place on a particular input; naming that input, and what goes wrong on it without the line, is the explanation.
Breaks down when: a rope's job shows on deck, but a line's case can sit in another module or on a server's contract, so the reader has to go and find it. And a crew can't test a gybe safely, while code can run both versions in a second.
Contrasting case: const total = price * qty; needs no "why": it is the computation itself, and removing it breaks every input. Explaining earns its keep on lines that matter for one case.
Examples, run for real
4.1 ExamHall EXH-3050: "what happens if we remove this await?"
EXH-3050: in a practice AI-assisted round, the interviewer pointed at await Promise.all(answers.map(save)) in the candidate app's autosave and asked why it was there. The candidate's first answer was "it saves all the answers in parallel", a paraphrase. Both versions, run with every save succeeding and with q2's save refused:
4.1 with the await, all saves succeed: flush start > saved q1 > saved q2 > flush done: mark saved · returns 'saved'
4.1 with the await, q2 refused: flush start > saved q1 > flush failed: keep for retry · returns 'retrying'
4.1 without it, all saves succeed: flush start > flush done: mark saved > saved q1 > saved q2 · returns 'saved'
4.1 without it, q2 refused: flush start > flush done: mark saved > saved q1 · returns 'saved' · unhandled rejection: q2 save refused (503)
The explanation: it starts every answer's save and waits for all of them (does). It is there because the next line tells the candidate the work is saved, and a refused save must land in catch so the answer is kept for retry (the case). Without it, "flush done" logs before any save, and a refused q2 is reported saved while its rejection has no handler (breaks; the record's step 9 says why Node ends the process).
4.2 Proof domain, payments ledger: paraphrase against explanation
4.2 deposit 100.00, posted payment -25.00, pending card hold -40.00: with the filter line 75.00 · without it 35.00
.filter((e) => e.status === 'posted') "keeps the posted entries" is the paraphrase. The explanation: a pending card hold is not money moved yet, so the available balance must ignore it; without the line, an account with a 40.00 hold shows 35.00 instead of 75.00.
Try it
Answer first, then check. Nothing is saved.
Question 1 of 7
A payments ledger's statement endpoint. MR !3351, "tidy: drop the redundant 0", changes one line, so that after the merge it reads const balanceCents = entries.map((e) => e.amountCents).reduce((sum, c) => sum + c);:
Account acc-9 was opened today and has no entries yet.
After the merge, what does GET /accounts/acc-9/statement return?
// src/statements/statement.js (excerpt)export function statement(account, entries) { const balanceCents = entries.map((e) => e.amountCents).reduce((sum, c) => sum + c, 0); return { account: account.id, balanceCents, lines: entries.length };} // GET /accounts/:id/statementexport function getStatement(db, accountId) { try { const account = db.accounts.get(accountId); return { status: 200, body: JSON.stringify(statement(account, db.entriesFor(accountId))) }; } catch { return { status: 500, body: JSON.stringify({ error: 'internal' }) }; }}Question 2 of 7
The ledger's endpoint for posting an entry. MR !3352, "codes are upper case in our API docs", deletes the line const currency = body.currency.toUpperCase(); and passes currency: body.currency to postEntry instead. Account acc-2 holds euros:
Which review comment names a real defect in this MR?
// src/statements/post-entry.js (excerpt)export function postEntry(account, entry) { if (entry.currency !== account.currency) throw new LedgerError('currency mismatch'); return { ...account, balanceCents: account.balanceCents + entry.amountCents };} // POST /accounts/:id/entriesexport function onPostEntry(db, accountId, body) { const currency = body.currency.toUpperCase(); const account = db.accounts.get(accountId); try { const next = postEntry(account, { amountCents: body.amountCents, currency }); db.accounts.set(accountId, next); return { status: 201, balanceCents: next.balanceCents }; } catch (e) { if (e instanceof LedgerError) return { status: 422, error: e.message }; throw e; }}Question 3 of 7
A box office's seat service. The buyer's Cancel button and the expiry job, when a hold runs out, both call it:
A sale clears the hold: holdId and heldBy become null, and status becomes 'sold'. Seat D12 starts each situation held as h1 by buyer b1.
Which situation is the only one where deleting if (seat.holdId !== holdId) return seat; changes the seat afterwards?
// src/listings/release-hold.js (excerpt)export function releaseHold(seat, holdId) { if (seat.holdId !== holdId) return seat; return { ...seat, holdId: null, heldBy: null };}Question 4 of 7
ExamHall's exam page runs tick once a second while the page is awake. MR !3353, "countdown: drop the clamp", deletes const remainingMs = Math.max(0, attempt.endsAt - now); and computes const remainingMs = attempt.endsAt - now; instead:
ECON-201 ends at 10:30:00. The candidate's laptop sleeps at 10:29:50 and wakes at 10:30:40.
After the merge, what does the first tick after waking do?
// src/exam/countdown.js (excerpt)export function format(ms) { return `${Math.ceil(ms / 1000)}s`;} export function tick(attempt, now, ui) { const remainingMs = Math.max(0, attempt.endsAt - now); ui.show(format(remainingMs)); if (remainingMs === 0) ui.submit();}Question 5 of 7
The interviewer is pointing at if (entry.currency !== account.currency) throw new LedgerError('currency mismatch'); in P2's postEntry. In at most three sentences, say what it does, the case it protects, and what breaks without it, with one input and the wrong result.
Why is this line here?
Question 6 of 7
The box office's listing page. MR !3354, "Math.min copes with an empty list", deletes if (open.length === 0) return null;:
After the merge, every section of the Friday show has 0 seats left.
What does its listing tile say?
// src/listings/cheapest.js (excerpt)export function cheapestPrice(show) { const open = show.sections.filter((s) => s.left > 0); if (open.length === 0) return null; return Math.min(...open.map((s) => s.priceCents));} export function tileLabel(show) { const price = cheapestPrice(show); return price === null ? 'Sold out' : `From £${(price / 100).toFixed(2)}`;}Question 7 of 7
A team chat's unread badge. Each of a member's devices sends its own receipts, each saying "read up to message N". MR !3356, "markRead recomputes everything anyway", deletes if (upToId <= conv.lastReadId) return conv;:
The channel holds messages 1 to 45.
Which review comment names a real defect in this MR?
// src/messages/read-receipts.js (excerpt)export function markRead(conv, upToId) { if (upToId <= conv.lastReadId) return conv; return { ...conv, lastReadId: upToId, unread: conv.messageIds.filter((id) => id > upToId).length };}Go deeper
Pro tip
- Try the edge in a one-line run before you answer. When an interviewer asks "what if it's empty?" or "what if it's late?", a
node -pof the one expression on that input takes seconds and beats a confident guess about the language. When: any "what would this return if…" follow-up you are not sure of (step 4). Verify (RAN,tips.mjs):
Status: RAN.tip node -p "'10' < '9'" -> true (strings compare character by character)
Source
Every behaviour this lesson grades is executed on Node 24.21.0; the sources support the steps and key nothing. Valid as of 2026-10-06.
- Hello Interview, Meta's AI-Enabled Coding Interview (the curriculum row's first source), https://www.hellointerview.com/blog/meta-ai-enabled-coding (
hellointerview-meta-ai-coding.txt). A preparation guide built from candidates' reports and one quoted internal source, about a company practice, as of 2026-10-06. Quoted: "Should use AI, but need to show you understand the code. Explain the output. Test before using. Don't prompt your way out of it." Motivates step 1. - interviewing.io, How is AI changing interview processes? (the row's second source), https://interviewing.io/blog/how-is-ai-changing-interview-processes-not-much-and-a-whole-lot (
interviewingio-ai-interviews.txt), as of 2026-10-06. Quoted, an interviewer at Atlassian: "how to ask follow-up questions or prompt the candidate to explain their thoughts/code". Motivates step 2. - MDN, Promise.all() (the row's third source), https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all (
mdn-promise-all.txt). Quoted: "It rejects when any of the input's promises rejects, with this first rejection reason." - MDN, Array.prototype.reduce(), https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce (
mdn-array-reduce.txt). Quoted: "if the array is empty (so that there's no first value to return as accumulator ), an error is thrown." Supports step 7. - MDN, Math.min(), https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/min (
mdn-math-min.txt). Quoted: "the smallest of the numbers given as input parameters, or Infinity if there are no parameters." Supports step 7.
Related lessons
Checked against the tools and docs as of 2026-10-06.