Part three opens
Patching the kernel
Chapter eighteen
Part two is over. The toolkit is in your hands. The remaining four chapters of this book are about what to do with the toolkit, which is, in plainest English, to use it to install new behaviors.
I want to be careful about how I say this, because there is a version of this argument that has, over the last twenty years, been sold to a great many anxious people in the form of productivity systems, life-hack newsletters, morning routines, and habit-tracker applications, and the version of the argument I am about to make is, in important ways, not that version. The version sold to anxious people in those packages has the property of treating the human mind as a piece of consumer hardware that can be reprogrammed by sufficiently disciplined sticky notes. The mind, in practice, does not work this way. The reprogramming, in practice, almost always fails, in part because the framing is wrong.
What I am proposing is something different and, I hope, more honest. I am proposing that the small, specific, hard-won responses to the bugs we examined in Part two are, in a strict technical sense, algorithms, and that they can be designed with the same discipline a working programmer would design a piece of production code. The discipline includes a specification, an invariant, an exit condition, and, importantly, a fallback for when the algorithm does not work as intended.
This is not a productivity manual. The algorithms worth installing are not, in general, about being more efficient. They are about handling, gracefully, the specific moments when the legacy code from Chapter 1 attempts to run a function call that you have, on reflection, decided you no longer wish to make. They are small. They are unspectacular. They are, on the whole, much more useful than morning routines.
Let me start by saying what an algorithm actually is, because the word has been bandied around so widely in the last decade that it has, in casual usage, lost most of its precision.
An algorithm, in the strict sense given by Donald Knuth in the foundational treatise The Art of Computer Programming, has five properties. It is finite, meaning it terminates after a definite number of steps. It is definite, meaning each step is unambiguously specified. It has inputs, which are values supplied to it at the beginning. It has outputs, which are values it produces in relation to its inputs. And it is effective, meaning each step can in principle be carried out by a person with a pencil in a finite amount of time.
An algorithm is not, in this technical sense, a list of suggestions. It is not a vague intention. It is not an aspiration. An algorithm is a precise sequence of operations that, given a defined input, produces a defined output, terminates in a defined amount of time, and whose every step is sufficiently specified that two different people following it should produce the same output.
This precision is, I want to suggest, exactly what the anxious mind has been failing to apply to its own behavior. The anxious mind has been telling itself, for years, things like I should be calmer at three in the morning, or I should not micromanage my colleagues, or I should stop ruminating about that conversation from last week. These are not algorithms. These are wishes. The mind, in attempting to act on them, has no specified input, no specified procedure, no specified output, and no specified termination condition. The wish has no executable form. The wish, in technical terms, is not implementable code.
The move I am proposing in this chapter is to convert wishes into algorithms. Not all wishes can be converted, and not all that can be converted should be. But for a surprising fraction of the recurring problems the anxious mind cycles through, there is, in fact, an algorithm that can be designed, written down in a small number of steps, and rehearsed until the mind runs it automatically when the relevant input arrives.
I want to show you, on the page, what one of these algorithms looks like, because abstract advice about designing algorithms is exactly the kind of thing that, in the absence of a worked example, evaporates the moment you put the book down.
The example I want to use is one I have, with some difficulty, developed for myself over the last several years, to handle the specific moment I described in Chapter 12 and again in Chapter 14, namely the moment when I notice the impulse to micromanage someone else's work. The impulse is, by now, well-mapped territory. The legacy code that produces it is older than I am. Recalibration in the Part-two sense is not enough. The impulse comes anyway. The question is what to do in the small window between the impulse arriving and the impulse being acted on.
Here is the specification of the algorithm I run.
The procedure itself is short and unspectacular. It is the kind of thing that, written out, looks almost embarrassingly simple. Here it is.
Figure 18.1 A small algorithm in flowchart form. Two decision points, four exits, and a clear default at each step. The whole thing fits in one diagram, which is, in technical terms, how you know it has any chance of running reliably.
That is the algorithm. Two decision points. Four possible outcomes. Each outcome is a defined action with a defined termination. The whole thing fits on one page. The whole thing can be rehearsed in under a minute. The whole thing, importantly, can be written down on a small piece of paper and kept somewhere accessible, until the brain has, by repetition, internalized it.
I want to point out three things about this algorithm, because they are, on inspection, the things that make it work where the wish version did not.
First, the algorithm has a clear input. It does not run all the time. It runs only when I have noticed the specific internal state of I am composing a critique in my head. The noticing is the precondition. Without the noticing, no algorithm. The first piece of skill is, in fact, the noticing itself, which is the work that Part two was largely about.
Second, the algorithm has explicit decision points. It does not say be wise. It says ask two specific questions in sequence, and the answers determine the action. The two questions are, on inspection, the operational reduction of an enormous amount of life experience into something I can actually do in three minutes. Question one: is this my call? Question two: will it matter in a week? These are not the only questions one could ask. They are, for me, the two questions that, asked honestly, reliably discriminate between cases where I should send the critique and cases where I should not.
Third, the algorithm has a fallback. If the algorithm fails to terminate in three minutes, which it sometimes does because the situation is more complicated than the algorithm anticipated, the default action is withhold and revisit tomorrow morning. The default is biased toward inaction, not action, because in this specific domain inaction is overwhelmingly the safer default. I am not designing an algorithm that produces the optimal critique. I am designing an algorithm that, by default, does not produce a critique I will regret.
The same shape, with different parameters, can be applied to any number of recurring problems. I want to write one more, in code form, to show what this looks like as a piece of actual Python, because seeing it as code makes the engineering nature of the exercise visible.
def handle_three_am_thought(thought):
"""
The algorithm I run when I wake up at three in the morning
with a thought that has the specific texture of being
catastrophic, urgent, and importantly unresolvable.
Designed in response to Chapters 9 and 10. Not optimal.
Good enough.
"""
# Step 1: name what just happened
label = label_thought(thought)
# 'rumination', 'cascade', 'real concern', or 'unknown'
if label == 'real concern' and is_actionable_before_dawn(thought):
# extremely rare; take the action and go back to sleep
return take_immediate_action(thought)
# Step 2: refuse to engage with the thought on its terms
if label in ('rumination', 'cascade'):
# the seed (see Chapter 11) is somewhere underneath this
seed = find_seed(thought)
write_down_on_phone(seed)
# the writing-down is the base case; the seed has been
# transferred from working memory into a system that
# will be there in the morning, so the brain can release it
return go_to_kitchen_drink_water_return_to_bed()
# Step 3: default fallback for the unknown case
return go_to_kitchen_drink_water_return_to_bed()
def label_thought(thought):
"""
Distinguish, with imperfect accuracy, between a real concern
and a piece of noise. Errs on the side of 'noise', because
in the small hours, almost everything is noise.
"""
if thought.is_concrete and thought.has_specific_object:
if thought.action_required_before_dawn:
return 'real concern'
if thought.has_what_if_cascade:
return 'cascade'
if thought.is_recurring_loop:
return 'rumination'
return 'unknown'
The code is not really code. The functions label_thought and find_seed are not implementable in Python in any literal sense. They are, on inspection, mental operations that I perform by hand, in approximately the order shown. The Python is a way of writing them down so that the structure is visible. The structure is what matters. The structure says: there is a defined input, a defined sequence of decisions, a defined output, and a defined fallback. The structure says: this is no longer a thing I do by reaching for whatever feels right in the moment. This is a thing I do by running a procedure I have written down in advance.
This is, in technical terms, the difference between an experienced engineer's response to a production incident and a panicking junior's. The experienced engineer has, over years, written down internally a small library of procedures for the most common incidents. The junior is reaching, in real time, for whatever they can think of. The experienced engineer's responses are faster, more reliable, and almost always less catastrophic. The skill is not, in the relevant sense, more intelligence. The skill is, in the relevant sense, more pre-written code.
I want to make one observation that the chapter has been circling, because it is, I think, the most useful thing the chapter has to say.
The anxious mind has been told, for most of its life, that good responses to difficult moments come from being a good person. This is, in technical terms, an instruction to optimize the moment from first principles, in real time, under stress, without any pre-written procedure. It is roughly equivalent to asking a junior engineer to handle a production outage by being a good engineer.
The instruction is, on inspection, almost designed to fail. Difficult moments are, by definition, moments in which the mind is operating under load. Operating under load is, by definition, when first-principles optimization fails. The mind, under load, reaches for whatever is closest to hand. If the closest thing to hand is a wish, the wish is what runs. The wish, having no procedure, produces whatever output the mind's untuned defaults happen to produce, which is, in many cases, exactly the response the person was trying to avoid.
The fix is not to be a better person under load. The fix is to write the procedure in advance, when you are not under load, in calm afternoon hours, with attention and care, and to make the procedure simple enough that, when the load arrives, the procedure is what runs. The procedure is not a substitute for character. The procedure is, on inspection, what character looks like in practice. It is the codified, pre-written form of the judgement you have been hoping to have available in the moment.
This is, I will note in passing, why the world's most reliable institutions are the ones with the best checklists. A surgeon does not, under the load of an operation, optimize from first principles. A surgeon runs a procedure. The procedure was written, slowly, over years, by surgeons in calm afternoon hours. The fact that the procedure exists, and is followed, is the reason most surgeries do not end in catastrophe. The surgeon is not, in the relevant sense, a better person than the rest of us. The surgeon has, in the relevant sense, a longer pre-written library of procedures for the specific moments when load is high.
You can write the same kind of library for the moments in your life when load is high. You are unlikely to need anything as complicated as a surgical checklist. You will need, at most, a small handful of small algorithms, each for a recurring moment that has, in the past, reliably produced an outcome you wish you had not produced. Each algorithm will be specified in advance, in calm hours. Each will be rehearsed enough that, when the moment arrives, the procedure is at least one of the things reaching for the controls.
A small exercise
Write one algorithm.
Pick one recurring moment in your life that has, on several past occasions, produced an outcome you wished you had not produced. The angry reply. The impulse to micromanage. The drink you did not want to take. The unread email you nevertheless opened at midnight. Whatever it is, choose one.
Now, in a calm hour, with pen and paper, write down a specification with the following five parts.
Name. Give the algorithm a name, in two or three words. Calling it something gives the brain a handle.
Input. What is the specific internal state, or external event, that triggers the algorithm? Write it concretely. Not "when I am stressed." Specifically: "when I notice myself starting to compose a sharp reply in my head."
Procedure. Write two or three small steps. Not more. The algorithm has to fit in working memory under load.
Default action. What does the algorithm do when in doubt? Bias the default toward the action you wish you had taken in past instances.
Fallback. What happens if the algorithm does not produce a clear answer? Specify the fallback explicitly, so that under load there is always something to do.
Keep the paper somewhere accessible. Rehearse the algorithm, mentally, three times this week. When the moment next arrives, you will find that some version of the procedure is already running, because the brain has, in the rehearsing, begun to compile it.
Chapter 19 takes the next step in Part three, into the question of how you test the algorithms you have written. The chapter is named for the engineering practice of test driven development, which is the discipline of writing the test before the code, and which has, when applied to human habits, a quietly devastating implication, namely that you have been measuring your own behavioral changes in the wrong way for most of your adult life.
For now, the page closes here. The wish has no procedure. The procedure is the form a wish takes when it becomes operational. Write the procedure. Rehearse the procedure. When the moment arrives, the procedure is at least one of the things in the room with you.