Reading Code Versus Understanding a Language
Date : 01 22 2008 Category : WebOne of the common complaints against Perl is that it’s “write-only”. For many Perl programmers, this is regrettably true. Perl, by design, allows you to get things done in a quick and dirty manner. It’s an explicit design goal which allows, amongst other things, the famous “one liners” in Perl which get so much done so fast. However, this freedom comes with a price and that’s a heavy price. Newer Perl programmers often write excruciating code, but experienced Perl programmers write code that is relatively easy to read, once you understand the language. There’s a huge difference between reading code and understanding a language. But when does a language go too far?
In a recent mailing list discussion, people complained about Perl 6’s shortcut for fetching the “metaobject” for a class:
if $class.HOW.can('some_method') { ... }; # .HOW fetches the meta object if $class.^can('some_method') { ... }; # same thingMy response was “if you can’t read my code, that’s my fault; if you can’t read my language, that’s your fault.” But in retrospect, maybe that wasn’t terribly fair. Consider the following Perl 5 code:
my ($var) = foo(); my $var = foo();Unfortunately, many books and training courses don’t do a good job of explaining context. Any reasonably experienced Perl programmer will glance at those lines and understand that the first is in list context and the second is in scalar context. Context is important in Perl 5 and if you don’t understand it, you don’t understand Perl. This is why I used to not understand this:
sub foo { my $var = @_; # do stuff }That’s almost guaranteed to be a bug, but if you don’t know context, you won’t know why. If you don’t know context, you’re not an experienced Perl programmer. Note that this is not an insult! I started out inexperienced in Perl. Lots of brilliant people will never even hear of Perl, much less develop a facility for it. However, here’s something which I’m embarrassed to admit sometimes gives me pause:
my @foo = @{$bar}{ qw/this that/ };I know exactly what it does (it’s taking a slice off of a hash reference), but whenever I hit that, I slow down. It’s a speed bump in the language. Some will argue that this is such an obscure feature, but is it? I’m not sure. I use stuff like that a lot because the alternatives aren’t much better.
my @foo = map { $bar->{$_} } qw/this that/; my @foo2; foreach my $key (qw/this that/) { push @foo2 => $key; }… and so on.
This is one of the reasons I think the Python folks have it so nice. Their language is easy to understand and this makes their code easier to read. Ruby is a little more dense, but I use closures so often that I think it’s a fair trade-off (Python’s trick of closing over a container is an ugly hack).
But when does a language become too complicated for people? It’s not necessarily the syntax. Many people will never understand Lisp or Scheme, despite the lack of syntax. COBOL’s syntax is very simple, but the sheer feat of memorizing all of the keywords is painful. Frankly, I have no idea the answer to this question and I’d love to find out if there are any reasonable studies in this area.