Teach Yourself a New Programming Language in 21 Minutes (Or 2-3 Years, It Depends)

You’re sitting at work, grinding out a bug in the legacy system, when your boss comes in and tells the team that you finally get the chance to rewrite the whole system–and even better, you get to do it in Clojure! (Or Scala or Erlang or Rust or Dart or some other Language You Only Know A Little About But Have Secretly Wanted To Learn For A While Now.)

Or maybe you’re happy with the language you’re using, but your VP of Software Architecture just spent $150,000 on a suite of Enterprise Tools which includes a module that will let your project scale infinitely into the cloud… all you have to do is learn Clojure. (Or Scala or Erlang or Rust or Dart or some other Language You’ve Only Heard a Few Mutterings About But Desperately Want To Avoid Learning.)

Either way, you’ve got a problem: you need to ramp up in this new language. And whether you want to become a super expert guru ninja rockstar in the language, or just learn enough of it to make it go away, you want to do it fast–and that means you want to avoid making the same mistakes I made learning Ruby and JavaScript over the years. Mistakes which I have learned to fix, mind you, and so without further ado I present:

Teach Yourself A New Programming Language In 21 Minutes (Or 2-3 Years, It Depends)

All you need to do to learn a new language is learn:

  • How the language encapsulates data
  • When the language invokes execution of code
  • Where do the semicolons and braces go

I’m not entirely kidding. This was my strategy for a decade and to this day if I need to get something bashed out quickly in a new language I’ll skim a language reference and let the compiler tell me when I make syntax errors.

In general, as long as you’re staying largely inside the world of what I call “BOLS” (Block-Oriented, Lexically-Scoped) Languages, such as C, C++, VB, Java, C#, PHP, Lua, Python, Ruby or perl, you can in fact learn enough pidgin to get by very very quickly with this method. Granted, in those last three languages it will be obvious to experienced programmers that you’re writing inelegant code. But you can get by, is what I’m saying.

If you’re the second kind of programmer I mentioned, you might be done. Just read this next section for a caveat and then you can hopefully stop there.

Don’t Stop There If You Can’t Stop There

As you’re learning the new programming language, ask yourself the two vital tradeoff questions:

  • Do I really want to learn this language bad enough to actually learn this language?
  • Can I afford the time and energy needed to fumble around being bad at this language?

See, this strategy is especially useful if you know you don’t plan to ever actually learn the language. I have written some pretty arcane bash scripts in my day, but to be honest I wrote my first bash script 10 years ago and in that time I’ve written less than 10,000 lines of bash scripting code. It’s just not worth learning to me, so I keep some files around with examples of the most obvious kinds of things I want to do, and when I need a new bash script–usually about twice a year–I have all the pieces I need right there. BAM. Ignorance is bliss, and laziness is, occasionally, brilliant time management.

But this strategy is especially awful if you know you don’t plan to ever actually learn the language, but you turn out to be wrong. It ends up that you find yourself using it on a regular basis, and hilariously, you don’t even notice this for years and years. This is true for me of elisp, the flavor of lisp used to program emacs. I’ve written elisp for years longer than I have bash, but maybe only twice as many lines of code. I find myself needing an elisp tweak on a weekly basis, and end up spending an hour researching how to do it. And two or three times a year I find a problem that I could solve elegantly in elisp, if only I knew how to express what I was thinking as lisp code. But I don’t solve the problem. I merely sigh, and learn to live without whatever cool new feature I was thinking of.

I wrote that paragraph in present tense because I still haven’t figured out that I really do need to actually learn that language. Shut up.

Sometimes work and politics can affect your decision as well. If you and your boss agree that the Next Big Thing will be written in Language Y, then you have the need and your manager has the afford.

(And sometimes these two forces are in conflict. I could write an entire blog post on the political machinations involved when you and your boss disagree on the do/don’t want or can/can’t afford questions. Skunkworking a cool language or shirking a lame one is a topic for another post, one I’ll probably never write, but basically it would be all about office politics. I’ve seen people get fired for a successful skunkworks project and others get promoted for sandbagging a project. People sure are complicated!)

Okay, NOW if you’re the second type of programmer, you can safely stop reading. If not, you’re pretty much out of luck for the “21 Minutes” part of learning a new language. But keep reading, because the 2-3 years bit isn’t until the very end. Most of the mistakes I’ve made learning a new language I have made in the first few days.

Truly Embracing A Language Takes Time, But You’re In A Hurry, So…

If you want to embrace a language, it’s going to take time. You’re going to have to internalize the language’s entire approach to solving problems. You’re going to have to learn its idiosyncracies and its warts, and you’re going to have to learn its power moves and elegant applications. That all takes time, but if you’ll permit me to point out my favorite pitfalls and some less-traveled paths around them, I can maybe show you a trick or two for leveraging your learning.

But first, good news/bad news. I’m writing this assuming you already know a programming language or three or seven. The good news is, the more languages you know, the faster you can recognize the basic syntax patterns and logic structures of a new language. But the bad news is: the more languages you know, the more they tend to blur into a common model of computation in your head. This can make you blind to the elegant weirdnesses of your new language. Resist the urge to judge weird things quickly; they often turn out to be the most powerful features of the language once you “go native”. If you see something you can’t stand, remind yourself that you haven’t seen everything there is to see, and give the new idiom a chance. Try it out and learn its tradeoffs. It’s okay to discard a bad idea in JavaScript once you understand why it’s a bad idea in JavaScript… but it’s never a good idea to discard a feature of a new language based on your instincts–because your instincts come from other languages, not this one. (Read up on The Blub Paradox if you haven’t heard of it before.)

TL;DR This Is Mostly About Your Blind Spots

I should have put that TL;DR up at the top, but if you don’t know by now that I’m that kind of jerk, you must be new. Welcome to my blog! Anyway, here’s the list. I’ve included illustrations about Ruby, Python and JavaScript, because those are the three languages where I stunted my own growth unnecessarily the longest.

  • As you start learning the core principles of the language, listen hard for hints and clues from its culture. Ruby has block syntax, but a rubyist often cares more about naming than blocks vs. Procs. Python has list comprehensions, but a pythonista often cares more about being able to quickly uncover all the working parts than to have a slick but magical-looking API. JavaScript has objects and polymorphism, but listen to a good JavaScript programmer and you’ll find them more interested in the functions themselves–and their prototypes.
  • Be ready to try totally new ways of thinking. Be ready to abandon bottom-up provability for Ruby’s top-down “programming by wishful thinking” approach. Be ready to trade off a more efficient algorithm in Python for one that is more readable and maintainable. Be alert to the pains you’ll feel trying to write object-oriented code in JavaScript–that’s JavaScript’s prototype system refusing to be hammered completely into an OOP-based inheritance model.
  • Learn where the minefields are. Ruby is a memory hog. Python’s primitives aren’t actually objects. All numbers in JavaScript are floating-point numbers–there are no integers.
  • Learn which minefields you can ignore or work around. Entire models of webservice design have been rethought and reinvented to compensate for Ruby’s apache-unfriendly execution model. Python isn’t THAT slow to begin with, but if you really need bare-metal speed it’s easy to write a C extension. Many JavaScript libraries provide “polyfills”–bits of code for old versions of JavaScript that implement features added to newer versions of the language so that you can write code against a stable JavaScript version and still have a prayer of it working in most browsers.
  • Most importantly, learn which minefields you CAN’T ignore. Treat them like minefields that you must commute through daily. Stop and pay close attention. Map them out carefully. For example, metaprogramming in Ruby is a very dangerous feature, but it’s not a defect; it can be used responsibly. Python’s whitespace enforcement makes it difficult to express certain ideas succinctly, but that whitespace enforcement produces a predictable rhythm to the trained pythonista’s eye, and it is most definitely a feature–don’t let your code fight it; learn to restructure your thinking. And while almost everybody considers JavaScript’s semicolon insertion rules to be eccentric bordering on insane, you MUST learn them if you want to avoid having your program suddenly stop working just because you deleted a comment or swapped the load order of two completely unrelated files.

You can make good inroads to these blind spots in a few days or weeks if you’re just aware of them. So here’s the hard part: Last of all, learn the idioms. From here on out it’s all about learning to think in the language. That’s going to take you a bit longer, and there’s nothing for it but to talk to other programmers, find some online references, maybe buy a cookbook… but mostly, it’s going to take writing code. Lots and lots of code. In my experience (both personal and observing coworkers and clients) this last part’s a doozy–plan on it taking a couple years or more.

Whaaat. You did say you really wanted to learn this language, didn’t you?

17 thoughts on “Teach Yourself a New Programming Language in 21 Minutes (Or 2-3 Years, It Depends)

  1. Wendy

    so, Sensei, is XAML an actual programming language or a collection of markup rules? (I have been asked if I want to “learn” this “language” at work today)

    1. David Brady Post author

      Sorry for lag in replying, this got stuck in the spamtrap.


      Okay, now then. Is XAML an actual programming language? Meh, probably not. It looks like a way of describing data, not a way of executing programs. In the context of my post, however, it’s safe to treat it like it is. Give it the 1000-foot flyover and decide if you want to just learn enough to hammer it into place and walk away, or if you really need to dig in and master its intricacies. As an example, I just gave it the 50,000-foot flyover (I googled it and clicked on one link and read for 15 seconds) and decided it was probably just fancy XML. But it could have execution rules, who knows? Heck, if it has loops and increments it’s probably Turing complete, which means that I’m wrong and yes it is totally a programming language.

      But ultimately? The advice is the same. Decide if this tool is worth learning. It’s okay to peruse a book’s cover, flip through a few pages, and then put it back on the shelf.

  2. Lironah

    I can vouch for the 21 minute thing – that’s about how much time it took me to learn enough Lua to repurpose someone else’s code today. I just wish I could say the same about Java. 😛

    1. David Brady Post author

      Awesome. Back in 2005 or so there were only 2 in-phone programming languages for PalmOS: Lua and Forth. Oh my word I probably wrote 10,000 lines of Lua code on that actual phone itself; I had to upgrade early because I broke the ‘z’ key. Never used Lua again… until the day we needed mysql-proxy to split writes to master and reads to a separate cluster. mysql-proxy is scriptable in Lua, so guess who got put in charge of the scripting. 🙂

  3. Prabhakar Mishra (@prab97)

    My opinion about this is: Learning a language is doable in 21 minutes but learning it and using it to build something even remotely useful takes 21 hours at least. Yes, you have to learn about the basic set of libraries also if you want to build something meaningful. And that takes some time trying and looking up on stackoverflow.

    1. dbrady Post author

      I think we agree. It’s definitely a sliding scale. I have built things in under an hour that proved to be immensely useful–but only because the tool or language was grounded very closely to languages I had 21 years of experience with. Other things I’ve spent all day on and gotten very little of use out of. Ultimately, the more use and value you want out of something, the more you have to invest, and the more leverage you can bring to bear on it the less you have to invest. But even if you plan to abandon the language after “this one thing”, if you want it to be robust you’re going to be fiddling with it, and yeah, that takes time. But then you’re back to the original premise: how much of this can I afford to NOT learn to succeed at this?


    1. dbrady Post author

      Are they? This doesn’t match my understanding. I can’t send the `real` message to `3`, for example: `3.real()`. I’m not an expert in Python anymore (if I ever was one), so I’d love to know if I’m missing something. Thanks!

      1. rdn32

        I just tried it out (in Python 2.6.1). You can’t use dot notation on an integer literal – presumably because allowing this would complicate the grammar. However, you there’s no problem using dot notation on an integer variable. There’s also no problem using dot notation on a float literal, although it does look a bit weird: e.g. “1.2.real”

        As it happens, “real” isn’t a method. However, there are plenty of methods defined on primitive types. For more details try “for name in dir(1): print name, type(getattr(1, name))” at a Python prompt.

      2. dbrady Post author

        I believe we’re in violent agreement. Variables aren’t primitives. Integer literals are, and IIRC Python directly uses C integers for them for speed until/unless you hit the 64-bit limit.

        Good spot on the dir call; I just did a dir(3) and picked real() at random. I didn’t realize it was an attr, not a method. 🙂


      3. rdn32

        No, I still think we disagree 😉

        I did a little bit more experimenting. You can’t say “3.real” because it gives a syntax error. That not, as I’d previously said, because you can’t use dot notation on an integer literal: “3.real” doesn’t parse as the integer literal “3”, followed by the dot operator, followed by the identifier “real”; it’s actually the float literal “3.”, followed directly by an identifier. That’s why it gives a syntax error – whereas “3 .real” (note the space before the dot) is perfectly legal.

        At some point I may say more about this – there are interesting subtleties that I haven’t mentioned – but I’ll post that to my own site rather than clutter up your comments…

      4. dbrady Post author

        Ah, interesting. I see the difference you mean. I’m used to the blurrier distinction in Ruby, where e.g. 3.to_str is legal syntax. Thanks!

  4. Pingback: 131 RR How to Learn

  5. Pingback: 164 RR Staying Sharp with Dave Thomas

  6. Pingback: Which Programming Language Should I Learn First? - Dother-Dev

  7. Pingback: Which Programming Language Should I Learn First? - Newbuster

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s