This is a useful collection of ways to think about programming languages, and has made me evaluate the languages I use or have used in ways that I had not considered before. I particularly hadn’t thought before about “What don’t you have to think about when using this language?”, but that’s an intriguing thing.
“The medium matters” led to a lot of ponderance too. Smalltalk was designed in tandem with its IDE and immediate, interactive GUI environment, then people saw the OO concept and extracted it into their text-editor-and-compiler toolsets. Does that work as well? I wrote an MSc dissertation on the converse question: can a later OO language (Objective-C) lend itself to a Smalltalk-style development environment? The answer was “not easily”.
I agree at the usefulness of this. I went in thinking “oh great, another troll post about PL design,” and left inspired by the insightfulness!
I really like the “not every is an X” and “extremist programming” points. Especially how they contrast with a different Perlis quote: “It’s better to have 100 functions that operate on 1 data structure (X) than 10 functions that operate on 10 data structures”.
“Everything is an X” gives you a lot of benefits, but it’s also where a lot of languages fall down:
As a specific data point: Lua is another “Everything is an X” language (everything is a “table”, a (possibly nested) key/value hash table that recognizes when it’s being used as array), but the escape hatch of conveniently doing things in C that are better done in C is pervasive in the language design. It seems like a sweet spot.
Tcl is another “Everything” language – everything is a string – but strings seem a bit too loosely structured. Still, Tcl works curiously smoothly as a shell, and has good support for quoting/wrapping other arbitrary data (such as with expect).
I think some of these are inconsistency problems, like, “everything is an x, except for y,” in situations where there isn’t a really good reason for y to be different, it was just convenient at one point.
In shell I think the way that process exit codes behave differently from other values (which are always strings) is weird and makes it harder to script
I think in Java that the weirdness around primitives being set entirely apart from object types is a good example of “everything is an object, except …” being a problem.
On a different note, I think “booleans and numbers are strings” isn’t the biggest problem for programming in Bourne shell. IME a much bigger problem is that the “everything is a string” rule doesn’t accommodate arbitrarily nested collections very well, so it’s very hard to structure data.
Not everything is an object in Java, and first-class procedures are very easy to encode as objects anyway (verbosely, of course). This just happens to be a foreign style for the Java community, and thus doesn’t get much support from either the standard library or the rest of the library ecosystem.
It’s also funny that you say more recent dynamic languages “make concessions to how computers actually work”, considering that Lisp implementations are sometimes competitive in performance with the likes of ML, Eiffel, etc. (of course, by selectively turning off the dynamism), whereas the main Python and Ruby implementations are consistently one or two orders of magnitude slower (and the only way to make things any faster is “call C, C++ or whatever”).
Re: “the medium matters”
I’ve always wondered how the existence of IDEs with their helpful features affected the evolution of Java’s syntax and standard library.
I know that C#’s LINQ syntax put “from ” first because it made intellisense easier in Visual Studio, related?