Programmers and Languages

I’m very much interested in the design decisions that go into making programming languages. As a result, I find myself in a lot of discussions about the pros and cons of different programming languages, and those conversations usually go beyond the “use X, you don’t need anything else!” that we all know and loathe from the intarwebs.

Personally, I have a strong background in Python and C++, so know at least one scripting language to the depth that I’ve read and fiddled with it’s implementation (CPython), and one compiled language to the depth that — despite that fact that it has a huge amount of features — few things surprise me there. I’m not a language lawyer, nor do I intend to become one though.

I suppose one of the reasons that I know those two languages pretty well is that I like a lot about them. I don’t really want to go into what specifically I like about them, but a consequence of knowing them so well is that I don’t always appreciate how complex they are. To me, there are just bits I know, bits I know a little less, and when I discover the occasional bit I don’t know, man am I chuffed to have learned something new!

Because those languages fit so comfortably in my mind, I’m usually fairly surprised — to the point of feeling ever so slightly offended — when people intensely dislike them. It’d be nice in a way if those people were idiots; unfortunately, most of them happen to be people I greatly respect. I needed to understand why this happens. Why is it that someone with that much experience, skill and knowledge holds such an utterly different opinion from my own? There is that nagging feeling that maybe they’re right, and I’m wrong. Inconceivable!1

Not so long ago I had a discussion with another developer whose opinion I value who extolled to me the virtues of JavaScript. I’m so used to dismissing JavaScript as “that language that ruins my browsing experience” that, while I can code in it, I never really bothered to look at it more closely than I absolutely had to. Again I was caught a little off guard by just how much this guy loved JavaScript.

And in the midst of our conversation, this guy said something that finally drove the point home to me. I can’t exactly recall what he said, but it had to do with the simple and powerful design of the language itself. The same argument, I might add, that proponents of C seem to make when they complain about the convoluted complexities of C++.

Simplicity, eh? I’ve heard this before, but for some reason it hadn’t clicked in my mind what it is they meant, because C++, Python, and all the languages I like seem simple to me. Clearly, I now realized, “simple” means different things to different people.

Here’s how I think that works, by analogy. Unfortunately, the analogy is slightly loaded with context that I’d rather not have here, but it’s the best analogy I could find: languages such as C, JavaScript, Lua, etc. are nails — languages such as Python, C++, etc. are screws.

The nail: a cylindrical object with a pointed end and a flattened end. You point the pointed (business) end at the material you want to fasten, then drive the point home by applying pressure on the flattened end. Simple.

The screw: a cylindrical object with a pointed and and a wider end, where the cylindrical part is covered in a spiraling groove. In order to fasten a material, you rotate the cylinder while applying pressure on the wider end… Simple? Oh no. There’s metal screws and wood screws. There are sunken screw heads, flat screw heads and rounded screw heads and that’s not all. Then for each head shape are slotted, cross, hex, torx and a ton of other screw drives. The combination of drives, head shapes and screw types makes for hundreds of possible choices when all you want to do is attach two pieces of material to each other.

What type of screw to pick? Fuck it, I’ll just use a nail instead.

I think that last paragraph pretty much embodies the attitude lovers of simple languages have, and how can they be blamed for it? After all, you can produce every program in, say, C, that you could also produce in C++. C is so much simpler.

I might not subscribe to the same ideal, but don’t let that convince you that I don’t think they have a valid point. They do. As is the case with screws, if there’s one good enough way of doing something, there’s no real reason for having two or more. I don’t for the life of me understand why there are so many different screw drives2.

The ideal of people who love simple languages is to have an easily comprehendable tool at their disposal, that they can then be inventive with. At the extreme end of that you’ll find people talking about how awesome Lisp is… and then you get this. Sure, as Lisp — or rather Scheme — code goes, this is easily readable, downright beautiful:

(lambda (f p)
  (define (save-item list count)
    (if (not (null? list))
      (let ((key (string-append "item" (gnc:value->string count))))
        (kvp-frame-set-slot-path-gslist f (car list) (append p (list key)))
        (save-item (cdr list) (+ 1 count)))))
  (kvp-frame-set-slot-path-gslist f (length value) (append p '("len")))
  (save-item value 0))

Yes, I can understand what happens in that random snippet well enough. Once I trained myself to just ignore the fucking parantheses and go by indentation (which is entirely optional in this language). And once I read each line very, very carefully.

In order to understand this snippet, first understand that kvp-frame-set-slot-path-gslit is a function that takes a kvp_frame, that is a data structure holding key value pairs (you don’t need to know more than that) as it’s first argument. The second is a value. The third argument is a key for that value, given as a hierarchical/namespaced path, which in this case is represented by a GSList, a particular list implementation.

Here’s the same thing in Python, minus the recursion, and ignoring that you can do the same thing a lot simpler if you stick to pythonic techniques:

def save_list(frame, path, list):
  kvp_frame_set_slot_path(frame, len(list), path + ["len"])
  for i in range(0, len(list)):
    kvp_frame_set_slot_path(frame, list[i], path + ["item%d" % i])
save_list(frame, path, value)

That’s right. It first saves the length of a list in this key value container, then each element of the list under they key “item”, where the number part identifies the position of the value in the list. I’ll assume that in the end, frame will be persisted somewhere to a file:

import pickle
pickle.dump(value, file("kvp"))

Yep, that’s what I would call simple.

  1. I know what the word means, but I use it differently anyway. []
  2. Actually I do, it’s all to do with patentability and control over what unlicensed engineers can repair. Patents are good for innovation… yeah right. []