Language Capability

I recently completely ported my site (which you are probably reading now) from PHP to Lua. This has got me thinking a lot about the overall capability of programming languages, particularly languages that see a lot of criticism, but also a lot of use.

Some of this overlaps with what I wrote about Tools and Correctness, but I think the train of thought is distinct.

Heated Motivations

I rewrote my site because I decided PHP itself was too much of a liability and frustration to continue to use. Luckily that the codebase is so small that a migration didn't cost much in terms of time or resources.

Magic quotes are a nightmare, it's easy to introduce subtle bugs by using == over === by mistake, everything is inconsistently named, many core language features are fragile (see (int)), many things that should halt execution just quietly log an error, and the OOP syntax is crappy and verbose. I got tired of PHP.

I don't deny it is a language widely used for getting stuff done, and it is a definitely capable language, but for the moment, I've had enough of it.

How this Relates to Capability

A lot of the most heavily used languages (C, C++, Java, Javascript, Python, PHP) levy equally heavy criticism. These languages must be capable, because so much is built in them, so why do they make some people so angry? Or if the criticism is valid, why do people use them so often?

I figured I'd provide my current set of criteria for evaluating a programming language's capability for a given task. The criteria are by no means exhaustive, but if you find yourself struggling against your current tech choices, they might be a good starting point.

Required Characteristics

There are several things a language can do "right" to make itself more capable. In effect, it's got to tick these boxes to truly be usable for your task.

  • Runs in your required environment.
    If not, you can't use it - give up and pick something else.
  • Gets you close to doing the work you need quickly.
    Think of what you need to do, and of a few different ways you'd like to do it. If the language (and its ecosystem) gets you several steps of the way there right out of the gate, that's a good thing. If it doesn't, that's more work for you before you get started on solving your task, which is not a good indication of capability. Think of this as the degree to which your required "batteries" are included. The faster you need to deliver, the more this one matters. It's hard to be anything resembling agile when you're reimplementing containers, rewriting basic sprite rendering, or cobbling together a http server.
  • Runs as fast as you need it to.
    It pains me to say as a game developer, but speed isn't everything. Writing your web request handlers in C++ probably isn't necessary unless you've got a much bigger site than mine. Even for many smaller games, being careful about algorithmic complexity will be enough. However, some tasks need to run quickly, or in parallel. You get bonus points for native compilation, JIT compilation and parallel programming options. The more performance-intensive your task is, and the more it needs to scale, the more this one weighs in.

Everything Else

This is the point where you might have expected points against capability, but as far as I'm concerned, the above points are the ones that matter. They're the things that determine if you can get software off the ground using a particular language. However, there are many other things that people argue over, and that you probably want to consider against your own baggage anyway.

  • Fits your preferred paradigm and syntax.
    Functional. Object Oriented. Procedural. Curly Brace. Operator Overloading. Closures. Duck Typing. All these get religious wars fought over them. None of them really determine whether a language is capable of a task, though they might make a language more or less attractive for some developers. If you can't stomach writing classes, don't choose to write Java every day.
  • Open Source
    FOSS is great. It also doesn't really change whether something is capable or not; many FOSS languages and libraries are crap. Many proprietary ones have been used extensively. The reverse is also true. It's a personal, political, and practical choice, but there's no universal "right answer".
  • Quality of Standard Library
    This is tangential to "batteries included". PHP comes with almost everything you could want - and for the things it doesn't, see the next point. The quality and cohesiveness however leave a lot to be desired. Whole essays could be written criticising the naming conventions (or lack thereof) alone. None of that stops you from getting work done, it just makes it less pleasant.
  • Has libraries/bindings available to speed things up.
    An ecosystem helps make up for things when the language takes a "some assembly required" approach. C and Perl definitely fit the bill, and a lot of C++'s strength comes from the entrenched ecosystem around it as well. That said, you can always build your own; it just takes time.
  • Package management that's auto-updated
    This is a great bonus in some cases, but windows programmers have managed with manual installation of C++ libraries for a long time, and there's always the chance of automatic updates ruining everything if there's no easy way to roll them back (looking at you, pacman, msys2, npm). The ramifications of one body deciding how your source tree should look are also considered "gross" by many.

Rebuilding My Particular Wheel

If you're an astute reader you'd notice that Lua doesn't tick so many of the boxes for my particular case - that's actually the motivation for this piece. I made the decision to switch based on quite a lot of the latter points, not the first ones. That may or may not have been a mistake.

Lua is a language not really intended for use on the web, not really intended to stand on its own at all. However, I am fairly familiar with it, and that I know does an ok job of working with strings, which in my experience is most of what web programming is anyway. It's got an acceptable (if pretty sparse) standard library, a decent ecosystem around it, and it's open source.

All in all, things went fairly smoothly. The site's size is down ~30 net kilobytes of code, most of which is a result of reduced necessary error checking and an overall terser language. There's also some libraries which were swapped in and out, though its hard to draw equivalences. Installing libraries or whipping up a quick helper when the standard lib was missing something (and it was) was reasonably painless, but I definitely picked the wrong language if I wanted "batteries included".

Some things were a pain (CGI in general is not great, sorting out package include paths properly took a little doing, Lua patterns are not regex...), but some things were nice. Things were quite reflective of this quote:

There is no perfect language, for programming the web or anything else. It's all about which brand of horrible you can best tolerate.

~jdw, NearlyFreeSpeech

It's true; programming is exhausting. There's a lot that can go wrong, and a lot of the more popular languages out there add their own special flavours of what can go wrong, be it dangling pointers, SQL injection, spaghetti inheritance, global by default, event handlers that don't return, garbage collection hitches, driver incompatibility, or undefined behaviour.

Your choices will often come down to what you know and like, and what you like really depends on what particular hitches are show-stoppers and which you can bear to deal with.

(That said, I might try a few other languages too, and see how they compare for this particular task. It's in a nice place where there's not that much code, but enough to sink your teeth in, so it might be a nice experiment when I've got the time.)

Previously...