What makes a programming language good? I propose:
The quality of a language for a particular domain is determined by:
-- JimLittle (thanks to ShaneWarden? and NickForrette? for their help in refining these ideas)
A year later, I think I have a better starting point...
(now back to the original discussion...)
Some examples:
C in the domain of device drivers:
Discussion
As of 2003-02-25, the discussion below is all between GarethMcCaughan (generally signed "--g") and JimLittle (generally signed "--JL"). GarethMcCaughan has done a bit of refactoring on it to avoid the disaster of InterleavedParallelThreadMode.
What does it mean for a language to reflect a domain?
I'm not sure that the crucial notion of a language "reflecting" a domain is any better defined than that of a language being well suited to a domain. For instance, suppose you're writing a flight simulator. No language (so far as I know) has anything much in it that's specifically tailored for writing flight simulators. Every serious language has the basic mathematical functionality you need. Does that mean that C++, Common Lisp, Fortran, COBOL and Visual Basic all score equally here? I hope not. --g
Well, yes. All score equally poorly on this point. Fortran might do better because it's got more mathmetically-oriented syntax. Lisp might do a little worse because it doesn't use infix (depending on whether flight simulator people think in infix or postfix). On the other hand, Lisp allows you to create new syntax, so that could be a saving grace. Introducing new abstractions is an idea I didn't really cover that perhaps deserves more attention. --JL
In that case, for a very large range of domains it's going to be true that no mainstream language "reflects" the domain to a significant degree. Hence my comments below under "Adaptability to a domain". -- GarethMcCaughan
Adaptability to a domain
It seems to me that a key question is: How easily can one extend the language and its libraries to "reflect" the domain? This depends on how well the language fits to begin with and how malleable it is. There will generally be some correspondence between malleability and support for the DRY principle, but these are separate issues. --g
Good point. --JL
What's magic?
I find the "no magic" criterion a bit unilluminating, too. Suppose you have a language that "reflects" its domain very well indeed; so well that a lot of the key abstractions of the domain are available directly in the language or in its libraries. Then a lot of important functionality will not be visible in the program -- but isn't that a good thing? --g
This is the point I struggled most with. Some languages have very syntactic shortcuts that lead to very complex results. So complex that it becomes nearly impossible for even experts to predict what the language will do. The interaction between templates and cast overloads in C++ is a one example. Perl is a more straightforward example.
I don't know how to say what I'm thinking in a simple way. Basically, I'd like a competant programmer to be able to understand the program without needing to know all the idiomatic "gotchas" and shortcuts. Some call it ThePrincipleOfLeastSurprise?, but I don't like that, because it's been used to excuse exactly the kind of behavior I dislike.
One last thing on this: I wasn't trying to exclude reasonable abstractions. I'm okay with "read line from file;" abstracting the open and close operation. What I'm not okay with is a programming language that says "all programs start with an implied 'read line from file' statement unless the first statement has a 'read' keyword." Don't laugh! C++, Java, and Perl, all have constructs along those lines! --JL
The trouble is that one person's magic is another person's convenience, and that with enough experience of a language nothing is very surprising any more. (With some languages, such as C++, it is possible that "enough experience" is more than one can attain in a single lifetime without insanity.) Declaring "magic" bad amounts to saying "no language features you have to get used to", which isn't a bad principle but may make it impossible to provide important conveniences to more experienced programmers.
My taste, like yours, is for languages where there isn't much "magic". One of my languages of choice is Python, where "Explicit is better than implicit" is a major design principle both for the language and for programs written in it. And I, too, shudder at some of the things Perl does. On the other hand, it's not clear to me that they're all really bad, rather than just not to my taste.
How about the following principle? "Everything a program does must be visible in its code at some level, clearly enough that an averagely experienced user of the language can reasonably be expected to know, at least, where to find an explanation of what's being done." Maybe that's too weak; it's certainly not snappy. --g
Partitioning language applications into domains, and in other ways
It's true that the quality of a programming language depends on the domain it's to be used in. But (1) it depends on a bunch of other things too, such as who's going to be using it, and (2) it's reasonable to ask for some measure of overall quality across a variety of domains. Ultimately, the quality of a language is only defined when you specify every detail of how it's being used, by whom, for what, in what environment, and so on. Anything more general is an approximation, and that applies just as much to "for log file analysis" as it does to "er, for, y'know, all that programming stuff". The only difference is that broader sets of language uses inevitably produce less precise measures of suitability.
And one can slice the space of language uses in ways other than by "domain". For "applications where you need all the speed you can get, but also require quick and easy portability across a very wide range of systems of various sizes", it's a fair guess that C will come out comfortably on top, despite its many deficiencies. Not that that's as important a set of language uses as is commonly thought :-).
And there are some issues that are completely ignored by the criteria above, which I can't believe have nothing to do with the quality of a language. For instance, whether it's feasible to implement it so that programs written in the language run quickly. --g
I think looking at the domain is more interesting than the other variables. --JL
Sometimes. But consider: when someone is wondering "What language shall I learn now?", what they care about its its quality for the set { things I'm going to do in the next while }, or something like that. For many people, most of those things will be in a small range of domains, but not for everyone. When someone's designing a new language, what they care about is whether there's any large and reasonably coherent set of uses that they can greatly improve; they might target novice programmers, or applications where the only thing that matters is maximum speed, or programming within a particular company.
Three of the languages I like best are C++, Python and Common Lisp. I like C++ because it makes it possible to write very fast programs that are still very portable; I like Python because it's possible to write software in it quickly and have something you can return to 6 months later and still understand it; I like Common Lisp because you can do just about anything in it, even if you haven't quite worked out yet what it is that you want to do. None of these qualities is domain-specific, but for the most part the domains I work in aren't closely enough modelled by other languages to make anything much better for me than those three languages. --g
If I might use an allegory, while domain influences language, I would suggest that commerce, i.e., the transaction between domains, influences language more than domain. -- JonathanSmith