How I learn new systems languages
Mar 20, 2022
I still dabble in some coding from time-to-time. A personal project here and there, maybe spiking out a proof of concept for a new idea. But it's been a long time since it's what I was actually paid to do. Even back when I was paid to do it as a core part of my role I skewed more towards systems programming. CLI tooling, services, and the barest of web/frontend competencies. I've always enjoyed playing with front-end tech like React, Elm, and Svelte because it's pushed me in uncomfortable ways. Forced me to wrap my head around new concepts. And be ok with the fact that I'm kinda rubbish at designing exceptional web-based experiences.
Systems langauges, and the jobs I need them for, that's a different story. My relationship has always felt more transactional. I have a job I need to get done. It's likely just the latest version of a problem I've already solved multiple times over the previous decades just with some new nuance for the current context. I want the quickest and easiest solution, and the one that is easiest to maintain. Quickest and easiest is most often a proxy for familiarity. Whatever language I'm most comfortable with is almost always going to win out over the combined cost of learning a new language and then solving the problem. To keep myself sharp I used to regularly join hackathons and use it as an excuse to try and pick up a new language. I'd often spend a weekend reading documentation and fundamentals but ultimately have nothing to show for it. One day at such an event someone I really respected seemed puzzled by my approach, "I dunno man. I have a rule: don't learn a new language on a new problem. There's too many unknowns when things go wrong. Did I create a bug? Is my design wrong? Is it a quirk in the langauge? Solve new problems with languages you know. Learn new languages with problems you already know the answer to".
He was right.
Picking up a new systems language has been so much easier since then. As I said, so much of the day job is new versions of a problem I've seen before. Taking his advice of solving a previous problem meant I could build myself a mini curriculum to learn any new language. Learn these fundamental tasks and I can be moderately productive in a new language. My time can then be spent increasing familiarity with the standard library and larger ecosystem. Focus on the idiomatic ways of doing things in that language. Basically, focus on the unique parts that make the language different and interesting.
What I've learned to love about this approach is that the goals are objective outcomes. It's not concepts that typically have hundreds of slightly nuanced and context-dependent decisions to make like "learn the different approaches of modifying control flow". It's "read an environment variable". For some languages that almost trivially easy (e.g., Ruby). It might only take a few minutes to achieve. And that's ok! You can call it done for the day and come back tomorrow, or continue on to the next things. For other languages that simple task might already be enough for force you to understand the idiomatic approaches to error handling (e.g. Go). All these things combined implicitly require you to start layering in the more foundational 101-level requirements of variable assignments, defining types, importing modules/stdlib, etc.
And before you know it, you've enough competency to start using it as part of your day-to-day toolset. Little scripts to scratch an itch. Tools to solve problems. But new (to you) problems. Problems you didn't already know the answer to.
Glenn's 14 step guide to learning a new language
This isn't the totally fool-proof plan for everyone. This is my plan. I'd recommend looking back over your own work for the past year or two and work out the most fundamental moving parts. Here's mine:
- Read a value from an environment variable
- Concatenate strings
- Extract a substring from a larger string
- Execute an external command
- Create a data structure (e.g. a class, type, interface, etc.)
- Make a HTTP GET request
- Make a HTTP POST request (with parameters)
- Parse a JSON string into a data structure
- Convert a data structure into a JSON string
- Parse a JSON string with nested objects
- Read a file from the file system
- Write a file to the file system
- Parse a URL into its constituent parts
- Respond to a HTTP request (i.e., build a minimal HTTP server)
Pulling it together
And with that, it's time to give you an example of how it works by learning a new language in the open. I've been wanting to learn Nim for a while now. And so it begins...