I think there’s an underexplored happy place (that D doesn’t entirely reach, but sort of gestures at) involving a fusion of Algol, Self, ML and the unlisted eighth language concept, metaprogramming (templates, macros, :gag: C preprocessor): pervasive type inference, mutable state in objects, immutable values with rich built-in semantics (tuples, sumtypes), lambdas and functional algorithms at the coarse domain level but (opt-in) mutable state (!) at the lowest level. The two big weaknesses of the ML family (IMO) are coarse state mutation and very fine algorithms; tail recursion is cute but iteration will always be nearer to the CPU’s heart. And even a ML program does (as a matter of observable behavior) have mutable state when it’s executed; OOP lets you model this fact where insistence on purity at all levels does not.
Then you end up, in the hexagonal model , with three levels that almost use entirely distinct languages:
Addendum: I think OOP gets a bad rap because people try to use it at the domain level, not the application level. A warning sign is when you see a class hierarchy that’s deeper than two levels. The important insight that classes should encapsulate components of the service as a whole that can change state and trigger actions independently. They should never represent values.
I would be more precise: Actors are missing. Actors are like objects and also like lambda calculi, so actor languages are like Lisps or Self; but the semantics are usually concurrent in a way which the typical Lisp or Self descendant lacks. The ur-language for concurrent actors is presumably E.
Or maybe Erlang?
Oh yeah, I wasn’t even thinking of that.
Arguably actors live on most prominently in the microservices/event-sourcing design.
If you want an absolute gem of a programming language, check out Factor.
The development of it seems to have slowed down a bit when Slava Pestov stopped working on it, but it was in an amazing state at that point already. It’ll rewire your brain because of being a concatenative language and how you can (or have to) do things.
Yes, I was about to recommend Factor as the first choice for Forthlikes. I don’t know gForth, but if it’s like most trad Forths it’s a lot harder to get your head around.
For learning how to build a Forth, good resources are JonesForth (x86 assembly) or Quackery (Python.) The former has exhaustively commented source code, the latter has a whole book describing the language and implementation. I recommend the exercise — I learned a LOT from reading the source code of FIG Forth for the 8080 as a teen.
Another great one is retroforth. Despite its name, it is a thoroughly modern forth. I feel like it combines some of the nice parts of Joy/Factor, while being a bit more simple. http://www.retroforth.org/
As for K’s, I think that ngn/k is the best one to try. https://codeberg.org/ngn/k
BQN would also be a great choice for an APL descendant language. https://mlochbaum.github.io/BQN/
Very relevant is Van Roy’s book and Oz, which attempts a similar breakdown https://www.amazon.com/-/es/Peter-Van-Roy/dp/0262220695
This poster summarizes Van Roy’s breakdown https://www.info.ucl.ac.be/~pvr/paradigms.html
I would add to this list:
Tcl is a beautiful fusion of both. Current programming is infested with too many bad versions of them!
I think lisp covers the macro category well. Your others are worth calling out specifically though.
I think textual macros have a significantly different flavour from Lisp macros, and a distinct history, going back to Strachey’s GPM in the 1960s.
TRAC and SAM76 are other significant macro languages. (Ted Nelson teaches TRAC in his classic book “Computer Lib”.)
No mention of the actual Ur language!
The article is mistaken: Forth was originally written iteratively over time in FORTRAN, as a helper deck of cards Chuck Moore would carry around with him begining as far back as the 1960s. Controlling radio telescopes was just his thing.
Very good list but I think that it’s worth considering scripting languages, in ergonomics if not particularly fundamental features. Command line languages (bash and its predecessors and descendents) fit into this category for me, but I’m not sure what the ur-scripting-lang would be for them. Perl is definitely notable but too recent; awk maybe? SNOBOL?
It is definitely lacking a lineage that starts with Z of formal modeling/constraint programming
I gave a list of 7 formal specification ur languages over at the orange site:
This is all real messy, and I see lots of overlapping concepts and unclear cases. Are state machines their own thing, part of LTS, or an implementation detail of the specification approach? Should we be distinguishing between the mathematical formalisms and the languages themselves? What about the vaster world of specifying code and not designs? etc etc etc
Great essay! A few thoughts / minor disagreements —