The standard, and the study routine built on it
Richard Feynman did not publish a four-step learning method. The routine that now carries his name was written up long after his death. Scott Young described it in 2011 as a way to study: pick a concept, explain it on paper as if teaching it, go back to the source wherever the explanation stalls, then simplify the language. Shane Parrish’s Farnam Street wrote the version most people meet in 2012. Explain it in words a child could follow, mark the gaps, organize what remains, and, if you want a final check, say it to someone else.
The routine is useful. The attribution is the interesting part, because the standard it is chasing is real, and it is stricter than the blog posts suggest.
In his 1966 talk “What is Science?”, Feynman tells a story about his father and a bird. A boy asks for the bird’s name. The father points out that you can learn what people in several countries call the bird and still know nothing about it: whether it sings, how it teaches its young, how it finds its way when it leaves. Feynman adds the line the technique is really about: he learned early the difference between knowing the name of something and knowing something.
Knowing the name, in programming, looks like being able to say “closure”, “debounce”, or “event loop” in a sentence that would pass in a meeting. Knowing the thing looks like predicting what a small program will print, including the case that breaks the sentence you were about to say.
The four moves
Do this on paper, or in a blank file. Speaking it only in your head lets the gaps stay fuzzy.
- Write the name of one concept at the top. One concept. “Async JavaScript”
is a syllabus. “What
awaitwaits for” is a concept. - Explain it in plain words, from the start, without the source in front of you. Use the kind of language you would use with a new teammate who has not seen this code. When you feel the urge to write a term you could not define, that urge is the signal, not the explanation.
- Find the sentence where you started waving your hands, and go back to the source for that part only. A textbook, the docs, the spec, a program you run. Fill the hole, then rewrite the sentence. Repeat until the explanation can be read straight through.
- Simplify, then test it on something that can disagree with you. Cut jargon that crept back in. Then teach it to a person, or write the smallest program that would behave differently if your explanation were wrong. The program is the better student. It has no patience for a metaphor.
The third move is the one people skip. They produce a tidy paragraph and stop. The tidy paragraph is where the illusion of understanding lives.
A worked example: closures
Here is the explanation that sounds finished and is only the name:
A closure is the combination of a function and its lexical environment.
That sentence is accurate and almost useless. Here is a first plain pass:
An inner function can still see the variables of the function that created it, after the outer function has returned.
That is good enough to generate an example.
function makeCounter() {
let count = 0
return () => {
count += 1
return count
}
}
const next = makeCounter()
next() // 1
next() // 2
const other = makeCounter()
other() // 1
Each call to makeCounter creates its own count. next and other do not
share one. The explanation survives this program. The next program is where a
common version of it dies. People say the inner function “remembers the values”.
Remembering a value means a copy. Closures do not take a copy.
function surprise() {
let n = 1
const show = () => n
n = 2
return show()
}
surprise() // 2
show was created when n was 1, and it returned 2. So the plain
explanation has to be rewritten. The function keeps access to the variable
itself, the binding, and reads whatever is in it at the moment the function
runs.
That rewrite earns its place on the classic loop, which is the program most people use to discover they do not understand this yet.
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 0)
}
// 3
// 3
// 3
var i is one binding for the whole function. All three callbacks close over
that same binding. The timeouts run after the loop has finished, by which time
i is 3. Nothing was copied at the moment setTimeout was called.
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 0)
}
// 0
// 1
// 2
let in the head of a for loop creates a new binding for each iteration. Each
callback closes over a different i. The behavior follows from the corrected
sentence. It does not follow from “a closure remembers things”.
An analogy that survives both programs: the inner function holds a handle to a
box, not a photograph of what was in the box. If some other code writes to the
box, the function sees the new contents when it next looks. let in that loop
gives each callback a separate box. The analogy fails if you stretch it into
“the function packs up everything it could see and carries a snapshot away”.
That is the photograph version, and surprise already showed it is wrong. Drop
an analogy the moment a program contradicts it.
What a bad pass looks like
The failure mode is a simple explanation that is simply false. “An electron can be in two places at once” feels like teaching, and it teaches the wrong model of superposition. The same thing happens with code. “JavaScript runs async functions in parallel” is easy to say to a beginner and will cause them to misread a race. A plain sentence still has to be true. When you cannot make it both plain and true, the concept is probably two concepts, and the page should be split.
The other failure is swapping one jargon word for a softer one and calling that teaching. “Lexical environment” becoming “the surrounding context” has not explained anything until you can point at the variable and say what happens when it changes.
Quote collections do not help with either failure. A line attributed to Einstein
or Franklin at the bottom of a study guide does not tell you whether your
explanation of var is wrong. Some of those lines are misattributed anyway. The
bird story earns its place because it names the actual mistake: stopping at the
name.
Using it while teaching yourself to program
After a tutorial, a docs page, or a chapter, close it. Write the explanation from memory before you write more code. The sentence where you hedge, reach for a term, or write “and so on” is the part to reopen the source for. Learn that part, rewrite the sentence, and leave the rest alone. Re-reading the whole chapter feels like work and rarely finds the hole.
Then write the smallest program that would fail if you were wrong, the way
surprise fails the snapshot explanation. Run it. If the output matches the
sentence, keep the sentence. If it does not, the sentence is what changes.
This takes about twenty focused minutes for one concept, which is the scale Scott Young suggested, and it is slower than highlighting. Highlighting leaves the name of the bird in a bright color. The blank page is where you find out whether you know what it does.