The DataLoader merged into pymc-extras this week. The number Week 11 promised — half a billion rows through the loader in six seconds, with memory never noticing — held up. But the thing I did most this week wasn't celebrating, and it wasn't racing to the next PR. It was rereading the editing pass my mentor Rob Zinkov (@zaxtax) made on my code before merging it.
How Rob edits code is itself the content
Seven commits, one idea per commit, the source file down from just over five hundred lines to 308. I expected to find rewrites. Instead, measured by git blame, 85% of the merged lines are still mine. Rob rewrote almost nothing. He deleted. That fact alone is worth sitting with: when an experienced maintainer reads my code, the question is never whether the lines are correct — it's which lines shouldn't exist.
What's interesting is how he described it himself. When I told him this week that I wanted to bring every PR of mine up to this standard, he pulled back half a step:
"My intention wasn't entirely to be like, hey, this is what I wish you had done — this is just what it looks like when I'm going through and saying, I don't need this, I don't need this, I don't need this."
He didn't frame the editing pass as a lesson. But precisely because it wasn't offered as one, treating it as one was my choice to make — seven commits, each message a reason, more concrete than any review comment could be.
Cut by cut: what each deletion means
I opened each commit separately and forced myself to guess what he'd cut, and why, before looking at the diff. Wherever I guessed wrong, that was a gap in my understanding. Over the weeks since, these operations have turned from "his preferences" into principles that mean something:
Decide the contract instead of supporting everything. My version tried to accept input in every shape, and every extra accommodation was another branch. His way: decide what the class promises and what it doesn't, then write code only for the promise. Deciding is harder than accommodating, because a decision takes responsibility.
Guards: delete the loud ones, keep the silent ones. I had written
isinstance checks and name checks and thought of them as rigor. He deleted
every guard whose failure announces itself — pass the wrong type and the next line
blows up anyway, with a message that's already clear; my check was noise on top of
noise. The one guard that stayed catches the failure that doesn't announce itself: the
fit succeeds and the posterior is quietly wrong. At our sync this week he
completed the philosophy out loud: guardrails get in the way of users, because the
user may know something about what they're doing that we don't — and when a
library doesn't know how to recover from something weird, the best it can do is warn
and then try something reasonable. Even an infinite stream gets the same treatment:
if you can't know N, don't scale, like NumPyro, and hope for the best.
An honest default beats a clever error.
An abstraction has to earn its existence. Private helpers called once, base classes with one implementation — taxes paid today for an imagined future. He inlined them all.
Prose is not free. A comment explaining what a line does is written for the reviewer; after the merge it becomes a burden on the next reader. The comments that stayed do exactly one job: record a constraint the code itself cannot show.
Precedent beats my own reasoning. What should len(loader)
return? I had derived my own answer. His: do what torch does — the intuitions
users already carry are the most expensive asset a library has. That one change rippled
through everything I had built downstream, and fixing it all is exactly why this is the
principle I now remember best.
Then I turned the knife on my own work
I distilled the seven commits into a checklist and went back through every PR of mine still open. The hard part wasn't deleting code — it was admitting that the reasons I'd had for writing those lines don't hold up under this standard. It got faster toward the end, because the test became simple: is this line paying rent?
Beyond the code
Three things Rob said in passing at our sync changed what I did next.
He told me to say so whenever something is ready for review, because he can't tell what's ready just by scanning it. Readiness is announced, not discovered — so when the Trainer PR went ready, it went with a line-by-line walkthrough laying out the reading path.
He'd rather see more PRs merged than any one of them polished. That set the ordering principle for the final weeks: the bare minimum that can merge beats any nice-to-have, and perfect is something you iterate toward after the merge, not something you hold out for before it.
And he mentioned, almost as an aside, that contributing to PyMC is just something he does every day. The lightest sentence of the meeting, and the heaviest. Open source isn't a summer sprint; it's a daily practice. GSoC ends. This doesn't.
Where things stand
The Trainer (#710) is marked ready with its walkthrough. The convergence monitor reopened as pymc-extras#733 — that redesign is next week's story. After that: cutting the tutorial down to the bare minimum that can merge. We sync again Friday.
Links. The merged DataLoader PR #698 · Week 9: deleting 300 lines · Week 11: three dead designs · GSoC project page · Mentors @fonnesbeck · @zaxtax