A tail call is a function call that is the last thing a function does before returning. That sounds like a minor implementation detail. It isn’t. Whether a runtime honours tail calls — replacing the current stack frame rather than pushing a new one — is the difference between recursion that scales linearly in stack space and recursion that uses constant space. It’s also where two languages I care about, Haskell and JavaScript, tell very different stories about the relationship between specification, implementation, and the reality of what you can actually rely on.
Around 2020 I made a deliberate decision to stop language tourism — spreading effort across Python, Ruby, and PHP — and consolidate around TypeScript. I haven't looked back.
The Context Switch Cost
For several years I was maintaining professional fluency across multiple languages simultaneously. Python for data pipelines and NLP work, Ruby on Rails for server-side applications, PHP surfacing in legacy projects, and JavaScript on the frontend. Each language has its own idioms, standard library conventions, ecosystem tooling, testing patterns, and community norms. I felt more marketable in the hiring game if I could claim expertise across all touchpoints.
Most developers know npm install, npm run, and npm publish. The rest of the CLI tends to be discovered only when something breaks — which is the worst possible time to learn a debugging tool.
These are the commands I’ve found myself reaching for repeatedly, in rough order of how often they actually come up.
npm explain
This one earns its place every time a dependency audit or lockfile conflict appears. npm explain traces why a package is in your node_modules — which package required it, and what required that.