You Are a Function

You are a function. Messily, impurely, but a function. I’ll lean on vocabulary from computer science, a lot of them are from functional programming in fact, not because humans are pure functions (we aren’t) but because FP has compact names for ideas that otherwise take long sentences. Programming is a well-studied domain. It has names for patterns that cause trouble and tools for dealing with them. When the same patterns show up in a life, we can borrow the tools, a mental model.

What I like about the programming lens is not that it explains everything. It doesn’t. What it does is shift where I look for leverage. When something in my life isn’t working, the first instinct is to push harder at myself — more discipline, more effort, more trying. This lens keeps asking different questions instead. What’s feeding the system? What’s wrapping it? What’s being repeated? What am I actually optimizing for? The lever is rarely where I first reach for it.


Inputs and outputs

A function takes inputs and produces outputs. You do the same.

Your inputs are longer than they feel: books, conversations, podcasts, videos, sure, but also relationships, the neighborhood you walk through, the vibe of the city, the events you show up to. Repetition too, it does something a first exposure doesn’t.

Your outputs are what you make, what you say, the decisions you push into the world. But functions also have side effects — things they do beyond their return value. For you, those are the ambient things: the mood you leave in a room, what someone tells their partner about you over dinner. People remember both. The mix is what sticks.

Outputs and side effects both trace back to what you took in. Garbage in, garbage out. You might object that humans aren’t passive — we select, reject, reinterpret. True, but the selecting itself is a function of earlier inputs. GIGO still holds; it runs over longer timescales.

You are not pure

A pure function returns the same output for the same input. add(2, 3) returns 5 today and 5 tomorrow.

You are nothing like this. Neither is your environment. You’re an impure function depending on hidden state: your mood, your sleep, the weather, what happened yesterday. It’s part of why changing your environment often does more than changing your mind.

Think of the environment as a higher-order function that wraps your function. The same input produces different outputs depending on the wrapper. Read a book in a loud café vs. on a quiet Sunday morning — same input, different wrapper, different output.

The wrapper isn’t just the room. It’s nested, and the outer layers matter more than the inner ones, in a lot of cases. You sit inside a conversation, which sits inside the friends you spend most of your time with, which sits inside the company you work for, the city you live in, the era you happened to be born into. Each layer shapes what your inputs become by the time they reach you. A brilliant idea lands differently in a startup than in a bureaucracy. A conversation about ambition means one thing in New York and something else in a small town.

So the decisions that end up mattering most are often decisions about wrappers. Who you partner with. Which company you join. What city you move to. Which five people you spend the most time around. These aren’t lifestyle questions — they’re environment compilers. They decide what every future input will do to you.

None of this is environment determinism. Internal work like grit, discipline, and persistence still matter — they’re what lets you navigate whatever wrapper you’re in. Not everyone gets equal say over their wrappers either; if you’re young, broke, or caring for someone, “just move cities” is glib. But the set of things you can’t change is smaller than it feels from inside, and internal work expands the set of wrappers you can reach. Internal work and wrapper work enable each other.


Learning is an optimization problem

Most functions have a fixed signature. You don’t.

I mean learning in the machine learning sense. ML models get shaped by the data you feed them — parameters get added, others pruned, the internals reorganize. Your body does too: running reshapes your body, a year of meditation reshapes your attention. The function isn’t static.

But shape change without direction is drift. What makes learning learning is that it’s pointed at something. In ML, the model optimizes against an objective — a loss function measures how wrong the model is on any given example, and training is the process of nudging the parameters so that number goes down. Everything the model becomes flows from what the loss function was asked to measure. Optimization is cheap; objectives are hard. Getting a model to minimize almost any loss function is a solved problem. Choosing what to minimize isn’t — and a model well-optimized against the wrong loss function is a well-optimized version of the wrong thing.

I didn’t have an explicit loss function for my life until recently. But I had implicit ones — the things I reacted to, the outcomes that made a day feel good or bad, the metrics I was keeping score against. They were doing the job of a loss function whether I’d examined them or not. When I finally looked, a lot of what I found wasn’t mine — it had come from parents, school, peers, the internet, and I’d never stopped to notice.

Which means learning splits into two modes that tug against each other. Exploration: figuring out what’s worth pointing at. Optimization: defining the objective sharply enough that each turn concentrates experience into a useful gradient descent. Machine learning calls this exploration vs. exploitation. In reinforcement learning, an agent chooses turn after turn between trying new actions and leaning into what already works. Neither works alone. Explore forever and you never go deep enough. Exploit too early and you lock into a choice you’ll later want to leave — painful, because the optimization was real; it happened on the wrong thing. The skill isn’t in the modes; it’s in how you play them — exploring deliberately rather than drifting, and when you commit, committing hard. Drift is not exploration. A lot of what passes for openness is delayed commitment without real discovery.

The balance is hard because turns are finite. With infinite time, there wouldn’t be much to balance — you could explore everything and exploit every branch. The budget forces the question of where to place each turn. I don’t have a clean answer for how to allocate it. Maybe there isn’t one; maybe the allocation is the game.


Connections are data exchange

To connect is to exchange data.

A conversation is two functions calling each other. Friendship is a long-running session. A city is a dense graph of function calls. The more you talk to someone, the more of their state leaks into yours, and vice versa. Close relationships aren’t just emotional — they’re informational. You share caches, shortcuts, references, inside jokes that stand in for long explanations.

A node in a graph gets important when many other nodes depend on it. In software we call those modules “load-bearing.” People work the same way. Importance isn’t about being impressive; it’s about how much of the system breaks when you leave.

Power is what you can reach, and what reaches through you

A function’s power has two directions. One is what it can call — what subsystems it can reach. A pure function that can only do arithmetic isn’t powerful; a function with IO access can change the world.

The other is how many things call it. A function a lot of other functions depend on has become an interface, a hub the system routes through. Not because it reaches far, but because the rest of the system reaches through it.

People work on both axes. Your power is partly what you can reach — capital, people, trust, information. But it’s also how many parts of the system depend on you. And these feed each other: the more things depend on you, the more resources the system hands you, which lets you reach further, which makes more things depend on you.

I’m still chewing on this. In software, this second kind of power is an anti-pattern. The module at the center of everything is brittle; changes to it break things downstream; it resists refactoring because too much runs through it. Good engineers split such modules into smaller pieces.

I don’t have a clean answer for whether life works the same way. But the brittleness shows up either way. The person everyone depends on tends to burn out, become a bottleneck, find it hard to leave. The anti-pattern doesn’t stop being an anti-pattern just because we’re the ones running it.


Recursion, reflection, and base cases

Recursion is how functional programs move. In pure FP there are no for-loops; iteration is a function calling itself, a little changed each time. Life works the same way. You today is a function of you yesterday, plus a small delta. A career, a relationship, a skill — each is recursion, the function calling itself one parameter at a time.

But recursion without a base case blows the stack. A loop without a termination condition isn’t progress — it’s a spiral. So: understanding your base case is what makes meaningful progress possible.

A base case is a predicate — something that answers “is this enough?” In practice, that’s your principles, your beliefs, your goals, your boundaries, your bottom lines.

Because I love her.
Because I said I’d show up.
Because I won’t do that for money.
Because past this point, more is not better.

Without these, the recursion keeps going, and you lose the ability to tell whether any given step is progress or regress. Movement becomes drift. Ambition becomes appetite without end. Anxiety is a stack overflow. Rumination at 3 a.m. is a function that forgot its terminating condition.

Recursion isn’t only how we move forward — it’s also how reflection works. Every time you think about your thinking, plan a plan, or write about writing, the function calls itself. Reflection is recursion turned inward — the thing being worked on is no longer out in the world, it’s you.

Every recursion needs somewhere to hold its state while it runs — that’s the stack. In life, stack is the weight of self-watching. Thinking about your thinking means holding the thinking in mind while also examining it. Add another layer — watching yourself watch — and you’re running the work plus two layers of commentary on top. The stack can get heavier than the thing you were trying to do.

Flow states are the opposite. Tail-recursive. Iteration without stack. No self-commentary, no meta-layer accumulating. Just the work calling itself forward.

The debugger is off by default

A debugger slows execution so you can see each step. It isn’t on by default; if it were, nothing would run fast enough to be useful.

Most of the time, you move through the day in compiled mode. That’s not a flaw — it’s the only way anything gets done. But if you never inspect anything, you end up living inside patterns you didn’t choose.

Why did that comment bother me so much?
Why do I avoid that task every single time?
Why do I become smaller around certain people?
Why am I optimizing so hard for something I don’t even respect?

Mindfulness — not the meditation kind, but the everyday state of knowing what you’re doing and thinking while you’re doing and thinking it — is a debugger. So is journaling. So is therapy. So is any practice that pauses the flow long enough to inspect a variable. You can’t run in debug mode all the time — you’d never get anything done. But without it, you don’t know why your function is producing the outputs it’s producing.


Functions that build functions

Some functions produce other functions. That’s what “higher-order” means in FP — map takes a function and applies it across a collection; a function factory returns functions tailored to whatever you pass in. It’s a whole category of work in life too.

Companies are the cleanest case. A company is a function — the law already admits this, a corporation is a “legal person,” same type signature as you: takes inputs (capital, labor, information), produces outputs, has side effects on cities, climate, culture. Internally it’s composed of smaller functions — teams, processes, pipelines. Culture is the impure wrapper shaping how every input gets processed. Zoom out far enough and an economy is one big composed expression.

The people who build companies are higher-order functions — their real product isn’t the company’s product, it’s the company itself. A founder starts with some capital, a few people, an idea, and returns a function. That function goes on producing outputs for years, decades, sometimes centuries after the founder has stopped touching it. The compounding is strange to sit with — their direct work ended long ago, but the function they wrote keeps running.

Founders aren’t the only case. Managers are higher-order in a smaller way — they don’t do the work, they compose the workers. Teachers might be the most underappreciated: they modify other functions, and one teacher reshapes thousands of them over a career. Parents too — likely the most consequential higher-order function a person can run.

One small note, because the higher-order framing can read as a ranking: it isn’t. In FP, functions are first-class values — they sit alongside other values, not above them. Higher-order work and base-level work are different structural roles, not different tiers.


What this lens has done for me

I said at the start that the lens shifts where I look for leverage. Writing all this out, I notice how much the same shape keeps repeating. Upstream, in the inputs. Wrapping, in the environment. In the objective I’m optimizing against. In the base case I stop at. In the graph I’m embedded in. In the moment I turn on the debugger. In the composition move where you build functions instead of running as one.

The lever isn’t where I first reach for it. That’s the whole thing.

It’s not a rule I can follow exactly. It’s an orientation. When I catch myself pushing harder at a function that isn’t yielding, the lens reminds me to back up and look at what’s feeding it, wrapping it, what it’s been asked to optimize for. Usually something gives. None of this replaces grit, persistence, or sustained effort — it helps me aim those better.

A few other concepts I haven’t worked out, but that keep catching my eye:

Memoization. The function remembers its past answers. Wisdom is memoization. You’ve seen this pattern before; you don’t have to recompute.

Closures. A function carries its defining environment with it. So do you. Wherever you go, your childhood kitchen is still a variable in scope. It’s part of why “just move to a new city” rarely works as a hard reset — the closure travels.

Dead code. Habits and beliefs you no longer use but still carry. They take up space. Cleaning them up is real work.

Garbage collection. Forgetting is a feature, not a bug.

Refactoring. You can reorganize your life without changing its outputs. A lot of therapy is refactoring — same behaviors, different internal structure, much more maintainable.

The metaphor breaks, of course. You’re not deterministic, not stateless, not cleanly composable. You’re a messy, impure, self-modifying process running in an environment with incomplete information.

But you’re, loosely, a function. And it works both ways — seeing life through code has been helping me work with life a little better, and for the first time I can remember, thinking about my life like code makes me want to write better code.