Succinctness is Power
[Succinctness is Power]
| "The quantity of meaning compressed into a small space by
algebraic signs, is another circumstance that facilitates
the reasonings we are accustomed to carry on by their aid."- Charles Babbage, quoted in Iverson's Turing Award Lecture |
In the discussion about issues raised by Revenge
of the Nerds on the LL1 mailing list, Paul Prescod wrote
something that stuck in my mind.
Python's goal is regularity and readability, not succinctness.
On the face of it, this seems a rather damning thing to claim about a
programming language. As far as I can tell, succinctness = power.
If so, then substituting, we get
Python's goal is regularity and readability, not power.
and this doesn't seem a tradeoff (if it is a tradeoff)
that you'd want to make.
It's not far from saying that Python's goal is not to be effective
as a programming language.
Does succinctness = power? This seems to me an important question,
maybe the most important question for anyone interested in
language design, and one that it would be useful to confront
directly. I don't feel sure yet that the answer is a simple yes, but it seems
a good hypothesis to begin with.
Hypothesis
My hypothesis is that succinctness is power, or is close enough
that except in pathological examples you can treat them as
identical.
It seems to me that succinctness is what programming languages are
for. Computers would be just as happy to be told what to
do directly in machine language. I think that the main
reason we take the trouble to develop high-level languages is to
get leverage, so that we can say (and more importantly, think)
in 10 lines of a high-level language what would require 1000
lines of machine language. In other words,
the main point of high-level languages is to make source code smaller.
If smaller source code is the purpose of high-level languages, and
the power of something is how well it achieves its purpose, then
the measure of the power of a programming language is how small it
makes your programs.
Conversely, a language that doesn't make your programs small is
doing a bad job of what programming languages are supposed to
do, like a knife that doesn't cut well, or printing that's illegible.
Metrics
Small in what sense though? The most common measure of code size is
lines of code. But I think that this metric is the most common because
it is the easiest to measure. I don't think anyone really believes
it is the true test of the length of a program. Different
languages have different conventions for how much you should put
on a line; in C a lot of lines have nothing on them but a delimiter or two.
Another easy test is the number of characters in a
program, but this is not very good either; some languages (Perl,
for example) just
use shorter identifiers than others.
I think a better measure of the size of a program would be the
number of elements, where an element is anything that
would be a distinct node if you drew a tree representing the
source code. The name of
a variable or function is an element;
an integer or a floating-point number is an element;
a segment of literal text is an element;
an element of a pattern, or a format directive, is an element;
a new block is an element. There are borderline cases
(is -5 two elements or one?) but I think most of them are the
same for every language, so they don't affect comparisons much.
This metric needs fleshing out, and
it could require interpretation in the case of specific languages,
but I think it tries to measure the right thing, which is the
number of parts a program has. I think the tree you'd draw in this
exercise is what you have to make in your head in order to
conceive of the program, and so its size is proportionate to the
amount of work you have to do to write or read it.
Design
This kind of metric would allow us to compare different languages,
but that is not, at least for me, its main value. The main value
of the succinctness test is as a guide in designing languages.
The most useful comparison between languages is between two
potential variants of the same language. What can I do in the
language to make programs shorter?
If the conceptual load of
a program is proportionate to its complexity, and a given programmer
can tolerate a fixed conceptual load, then this is the same as asking,
what can I do to enable programmers to get the most done? And
that seems to me identical to asking, how can I design a good
language?
(Incidentally, nothing makes it more patently obvious that the old
chestnut "all languages are equivalent" is false than designing
languages. When you are designing a new language, you're constantly
comparing two languages-- the language if I did x, and if I didn't-- to
decide which is better. If this were really a meaningless question,
you might as well flip a coin.)
Aiming for succinctness seems a good way to find new ideas.
If you can do something that makes many
different programs shorter, it is probably not a coincidence: you have
probably discovered a useful new abstraction. You might even be
able to write a program to help by searching
source code for repeated patterns. Among other languages, those
with a reputation for succinctness would be the ones to look to for
new ideas: Forth, Joy, Icon.
Comparison
The first person to write about these issues, as far as I know, was
Fred Brooks in the Mythical Man Month. He wrote
that programmers seemed to generate about the same
amount of code per day regardless of the language.
When I first read this in my early twenties,
it was a big surprise to me and seemed to have huge implications.
It meant that (a) the only way to get software written faster was to
use a more succinct language, and (b) someone who took the
trouble to do this could leave competitors who didn't in the dust.
Brooks' hypothesis, if it's true, seems to be at the very heart of hacking.
In the years since, I've paid close attention to any evidence I could
get on the question, from formal studies to anecdotes about individual
projects. I have seen nothing to contradict him.
I have not yet seen evidence that seemed to me conclusive,
and I don't expect to. Studies
like Lutz Prechelt's comparison of programming languages, while
generating the kind of results I expected, tend to use problems that
are too short to be meaningful tests. A better test of a language is
what happens in programs that take a month to write. And the only
real test, if you believe as I do that the main purpose of a language
is to be good to think in (rather than just to tell a computer what to
do once you've thought of it) is what new things you can write in it.
So any language comparison where
you have to meet a predefined spec is testing slightly the wrong
thing.
The true test of a language is how well you can discover
and solve new problems, not
how well you can use it to solve a problem someone else has
already formulated. These two are quite different criteria.
In art, mediums like embroidery and mosaic work well if you
know beforehand what you want to make, but are absolutely lousy if
you don't. When you want to discover the image as you make it--
as you have to do with anything as complex as an image of a
person, for example-- you need to use a more fluid medium like pencil or
ink wash or oil paint. And indeed, the way tapestries and mosaics are made in
practice is to make a painting first, then copy it. (The word
"cartoon" was originally used to describe a painting intended for
this purpose).
What this means is that we are never likely to have accurate comparisons
of the relative power of programming languages. We'll have precise
comparisons, but not accurate ones. In particular, explicit studies
for the purpose of comparing languages,
because they will probably use small problems, and will necessarily use
predefined problems, will tend to underestimate the power of the
more powerful languages.
[...]