Permission to Begin Learning: A Defense of Incomplete Knowledge
#Rust

Permission to Begin Learning: A Defense of Incomplete Knowledge

Tech Essays Reporter
7 min read

A personal reflection on learning programming languages without utility-driven justifications, exploring how incomplete mastery and multi-language exploration can enrich one's programming practice and mindset.

I like learning programming languages. You may think this goes without saying, considering that I'm, well, a programmer, but I don't think programmers necessarily like programming languages. Let me explain.

Two Perspectives on Programming Languages

I think there are two main perspectives you can have on programming languages. The first (and, I think, most common) is seeing them as tools: in other words, something we learn to use in order to get a job done. Thus, the object of study becomes the task, not the language. Programming languages each have their strengths, weaknesses, and kinds of tasks they're suited to tackling. If you're looking to build a career in, say, data science, you would probably learn Python. Not because you like Python more than the alternatives; but because Python is the (de-facto) data science language.

The other way to see programming languages is as themselves the object of study: as worth understanding for their own sake, not just as the means of completing some task. Sure, programming can be seen as an activity that provides strictly utility, but it's also a craft that its practitioners can take very seriously. Finally, there exists a kind of middle ground: learning new languages not with any particular task in mind, but anticipating that the language fills some niche that may become useful in the future.

It Doesn't Have to Be Useful

Note the emphasis on "may" above. There's no guarantee that the language will ever be the best tool for some job you do in the future; but that's besides the point. If it happens that you do encounter a task that can perfectly be solved by the language, that's great! But if you don't, that's okay too, because you've still gained something: experience, and a widened perspective on programming in general.

You don't need a reason to begin learning something new. The learning is the reason; I argue that it's never a bad idea to expand your horizons. Not only do you not need a reason, you don't need permission either. How often have you felt drawn to learn something new, just to tell yourself "I'll do it when I'm done learning X"?

Learning Is Never Done

This is what brings me to my central point: learning one thing does not block you from learning another. Stop gatekeeping yourself from pursuing knowledge! You may be in the progress of learning language A, but that should not stop you from also learning language B! The truth is that learning is never done! No matter how much expertise you gain in a particular area, there will always be something left to discover. Naturally, this applies to programming languages, too. Even if you know all the, say, keywords or built-in functions, there may be approaches or techniques you've yet to learn. If you waited to completely learn thing X before starting thing Y, then you're never going to start, because you won't ever be done with thing X!

It's OK to Half-Learn Stuff

If it's impossible to completely learn something, then at what point can we decide we've learned enough to move on to the next thing? Well, this is also why I argue it's totally OK to half learn stuff! All knowledge gained is valuable, even if it's incomplete! Whether you've learned 50% of what a language has to offer, or just a few of its functions, does that really matter? Whether or not you can actually implement a complete project is besides the point. Because even if you haven't really gained a tool that you can use in the future, you can always bring the mindset and concepts back with you to a more comfortable language.

My Experience: Starting Learning Rust

I've been learning some Rust recently. My motivations for doing so are mixed. On one hand, I do have a utility-focused goal: contributing to some of my favorite open-source projects, many of which are written in Rust. But my goal is also intellectual: I simply think Rust is neat, and I'm intrigued by its promises of elegance and correctness. After doing a bit of rustlings, I figured I'd give this year's Advent of Code a shot. Although I only solved the first three challenges, they were enough to get me comfortable with super basic input parsing and manipulating iterators & vectors.

Something I try to always avoid when learning a new language is imposing my own idioms onto it. In other words, when learning Rust, I try to learn the "Rustiest" way to solve a given problem. In the case of iterators, that seemed to be map and fold: functional programming patterns. Even though Python does have them via functools, I never engaged with the concept until Rust. However, I found out that I actually really enjoy this style of programming! So much so, that I had a thought: why don't I give a real functional language a shot? I could try coming up with some utility-based justification for this. Like, "maybe if I learn a functional programming language, I can build a stronger understanding of things like functional application and accumulators, and then I can bring that knowledge back to Rust, and write code that's cleaner and more correct." But I'd be lying. The truth is, I just wanted to learn it because it seemed fun.

Then Started Learning: OCaml

Learning OCaml has been a mixed hand. On one hand, the language is really pleasant. I just really, really, really enjoy writing it. The syntax is intuitive, explicit, and the type inference is really excellent. To begin my journey, I followed the excellent OCaml Programming: Correct + Efficient + Beautiful textbook. I haven't gotten to the "bring my new knowledge back to Rust" part, yet, so we'll see whether that ends up happening. But, I think that's besides the point! Because the truth is, I'm having a blast with OCaml.

I'm not convinced it'll be my "go-to" language for any and every problem (to be frank, the project/dependency management leaves something to be desired, and figuring out the linker, modules, namespaces, interfaces, etc. isn't fun), but I'm certain I now have a useful tool for solving certain problems. For example, OCaml is really well suited to the task of writing a lexer, parser, etc. Basically, programs that operate on other programs. It's actually so nice for this task that, even though I'm reading a book that's literally called Writing an Interpreter in Go, I'm actually writing my interpreter in OCaml.

Multi-Track Drifting

As my first "project", I tried porting one of my Kakoune plugins from Nim into OCaml (which was itself ported from my first implementation in Python). I figured this plugin would be well-suited to FP because it's essentially a stateless command dispatcher. However, as I got into it, I made a painful discovery: OCaml doesn't have any library to split & quote shell command lines! Where Python has shlex, OCaml has… nothing! So, I shifted gears and decided I would implement this library myself. Because such libraries exist in many other languages, I figured finding the Rust version and porting it 1:1 would be a good place to start.

Doing so was one of my better choices. This project taught me a lot about elegant lexing, threading a complex state through pure functions, and as a bonus, I got to practice reading and understanding Rust code. I even copied the Rust unit tests added implemented them to my own project with ounit2, and since they're all passing now, I'm pretty confident that my port matches the Rust library's behavior exactly. The shellwords package is now available on OPAM.

Closing Thoughts

I don't really know where any of this will lead. Maybe Rust will become a major part of my day-to-day work (it's already proved useful in its thesis work; its popularity means more libraries for working with niche protocols and formats). Maybe OCaml will become my favorite, or maybe it stays a language I reach for occasionally, when a problem happens to fit it particularly well. Or maybe I'll move on to something else entirely (Haskell & Zig are on my horizon…)

But, I'm increasingly convinced that none of that actually matters. Learning new languages has value even when your learning is incomplete, even when it's impractical, and even when it doesn't have an immediate payoff. Each one teaches you new ways of thinking, new abstractions, and new sensibilities that stay with you long after you've returned to your "ol' reliable" language.

Thus, I'll keep drifting between languages, half-learning some, borrowing ideas from others, and following whatever seems interesting at the time. It may not be efficient or career aligned, but programming is great fun, so why not learn new ways to have that fun?

Comments

Loading comments...