An opinionated history of programming languages
artagnon.com
artagnon.com
The exception is COBOL, which is still important in the way FORTRAN and Java are, but similarly will not affect future languages.
If this is meant to be any kind of history, that would seem to be grounds for inclusion. After all, Bourne Shell gets a spot, even though it's not actually a language and hasn't influenced any other language to any significant degree (unless you consider Tcl and even that's a big stretch). It seems like many things were included merely as excuses to express like or dislike, without any regard for historical importance or relevance. The fact that it favors C++ over alternatives might please some, but doesn't make it a good article.
And no, it is not the same concept.
When was the last time you had any contact with a running Algol or Simula program? I use sh -- bash, really -- every day.
Not the only area in which C++ is 30 years (and counting) behind state of the art.
> When was the last time
The OP is supposedly about history, thus current usage is irrelevant. There's no longer a Mongol Empire either, but its existence is still historically important and only the worst kind of dilettante would try to write a history of the world without mentioning it.
The author seems to prefer to mention languages that are still taught and used, and to neglect those that are not. It being an "opinionated" history, I can only find fault where he breaks his own rules. Maybe he should mention Korn shell, for example, which became Posix shell and bash. But only Bourne shell features affected modern languages.
I can't extract any value at all from this chart.
Rust not being a candidate for designing a future language?
But C++ being a candidate for designing a future language?
Go having remarkably poor design?
Ruby dying, but Python and Perl not?
I would really like to have a rationale for those decisions. It would be interesting to see how you can come to this conclusions.
Go's design is at the very least controversial and considered poor by a vocal subset of the hackernews and programming community.
Python is decidedly not dying... it's still the dominating game in town for ML and data science. I'm surprised anybody would posit that Python were dying. Perl definitely feels like it should be in Ruby's camp.
Python is the only language I've had to deploy that makes me understand why anybody would want to use containers.
Did you know that pip won't even resolve dependencies, and will break your programs silently? I certainly didn't, because Python wasn't my first language and therefore I assumed that the package manager will handle dependencies.
Like seriously, when a language designed by statisticians for statisticians (R) has a better packaging story than everyone's second favourite language, something has gone horribly wrong.
I almost used Perl as an example of Python's inverse - a crappy language wrapped in a good packaging system. For its time CPAN was pretty great. All of the things today that people are likely to hold up as being better drew inspiration from it.
> which is much older than Python
Perl 1987, Python 1989. So yes it's older, but much older?
I'm just so annoyed by Python's (lack of a) packaging system that it makes me prone to hyperbole. It's been frustrating me at work all week, and I suspect that it will be a low-grade annoyance for me in my career for the next few years, as I'm a Data Scientist and hence need to deal with Python a lot.
Spending a bit of time with Rust's tooling, static analysis, and "if it compiles it's pretty likely to work" (at least way more so than with Python) definitely emphasizes a lot of Python's flaws.
I'm in the camp of the rationales of Go's design being controversial. But the actual design is not bad IMO. For what Go wants to be (a modern C), it is not a bad design. But who wants a modern C? I don't. But if Go were available in the 90s, I would have jumped at the opportunity to write programs in it.
> Python is decidedly not dying... it's still the dominating game in town for ML and data science. I'm surprised anybody would posit that Python were dying. Perl definitely feels like it should be in Ruby's camp.
I didn't say that I would consider Python a dying language. But considering Ruby dying and Perl don't, is very weird. OTOH Ruby and Python aren't gaining any new usecases (but also aren't losing anything rapidly AFAIK) whereas Perl ... has any left besides very legacy code?
Putting Perl and Python into the same group and Ruby in another is certainly an interesting choice.
Sure and there's this weird thing where Go felt marketed as a C replacement and then Rust existed and it was all "just kidding we meant services" and boy do I think Go is poorly designed for services. It has a lot of characteristics that make it appealing - fast compiler and execution speed, low resource usage... but I don't see how pointers, a half-baked type system and a totally undesigned error system are good design for where Go is currently winning.
> But considering Ruby dying and Perl don't, is very weird.
Agreed for sure, I think Ruby and Perl probably have similar trajectories based on current trends in languages. Python's staying power IMO is really only due to the data science/ML trends and I frankly think it's a pretty poor language and ecosystem if you can get away with using anything else. I think Python WOULD be losing ground if not for its popularity in these very large niches.
Python will gain usecases as a meta-language as the ability to automatically wrap lower abstraction libaries improves. I see Julia eating much of Python's lunch, then python abstracting its way over julia, just because it can.
A big problem for Python as a glue language is interproceedural optimizations. In many important high performance applications, you really need the compiler to be able to make optimizations that cross function barriers, often barriers between user-written and developer-written functions.
e.g. in differential equation solving, you can have a very fast integrator, and your user can have a very fast integrand, but if you don't have a compiler that's able to see and reason about both simultaneously, you're in trouble.
This is why slapping Numba on a differential equation and sticking it in scipy integrators isn't even close to julia DifferentialEquation solvers. This is a very hard problem to solve in an ecosystem where there's so many different siloed compilers used by different Python packages. You'll always end up paying a performance price of the context switch.
In julia, most things are written in pure julia, so the same compiler is seeing the entire program top to bottom. It's very nice.
Furthermore, Julia has much power powerful metaprogramming facilities than Python does. It'll eat Python's lunch on that front too.
On the other hand Julia is a terribly designed language in some respects. Compare python error messages to Julias. It has all the problems of c++ templates baked in from the start. And latency is a real issue for now. I am always shocked when I drop back to Python for one task or another how responsive it feels.
I think the latter might see a technical solution some time, e.g. by running code in the interpreter and swapping in jotted functions as they become available.
The former it seems might have to wait for Julia 2.0 to start addressing...
> Furthermore, Julia has much power powerful metaprogramming facilities than Python does.
Until someone writes a way to import julia code directly into python/autogenerate it from python. Anyone who says "well then you're not really writing python" is missing the whole point: writing python is all about exactly this sort of tip-of-the-abstraction-iceberg trickery.
Sure, you can call python from Julia as well. So it boils down to "which is the better glue language?" This isn't a competitive thing, it's just literally what Python is meant to do.
As in, a minimalist language aesthetic or fast low-level non-gc? Golang only has the aesthetics, Zig has both.
https://trends.google.com/trends/explore?date=today%205-y&q=...
http://james-iry.blogspot.com/2009/05/brief-incomplete-and-m...
This is profoundly untrue. Its not an opinion, its simply wrong.
Other things said about Haskell, such as "memory leaks are difficult to debug" is the type of thing you hear people repeating a lot but I experienced very little of. Pretty much every language has flaws that are a bigger issue and cost more wasted time than that.
template <size_t i, typename... Ts, typename CurTy>
void recurseFillChildren(CurTy &E)
{
using PackTy = std::variant<Ts...>;
using TyL = std::variant_alternative_t<i - 1, PackTy>;
static_assert(std::is_same_v<CurTy, TyL>);
using TyR = std::variant_alternative_t<i, PackTy>;
for (i32 j = 0; j < E.NChildren; ++j)
{
E.Children.push_back(miniParser<TyR>());
if constexpr (i + 1 < sizeof...(Ts))
recurseFillChildren<i + 1, Ts...>(E.Children.back());
}
};
does, and why it can't be translated into Rust?And I will always prefer more verbose code that I can read, understand and maintain.
The key line is "if constexpr", which is evaluated at compile time and terminates the recursion.
struct A {vector<B> Children; int NChildren = 2, ...};
struct B {vector<C> Children; int NChildren = 2; ...};
struct C {vector<D> Children; int NChildren = 2; ...};
struct D {...)
and a function template template<typename T> T miniParser() { return T{}; }
and you call it like struct A;
recurseFillChildren<A, B, C, D>(A);
It expands into nested loops that fill the "Children" areas of each type with two default-constructed values of the next type down the hierarchy, until you get to D, at which point it does nothing.The reason you can't implement this in Rust is that Rust Generics (their "template-y" language feature) is missing a few capabilities relative to C++ templates. Namely,
1. They don't operate on numbers
2. They have no notion of collections of types
Because of this, they
1. Can't know that there is a collection of types
2. Can't extract the size of the collection of types
This comes up in numerical code, where in C++ it is easy to write e.g. geometry code that is generic in the number of spatial dimensions, but in Rust it is a pain in the ass.
https://www.amazon.com/History-Programming-Languages-Thomas-...
It's one those books I return to, every few years. Recommended. Maybe the papers are available online somewhere by now?
And C++ derives much from Simula which comes from Algol. And C derives much from Algol. And link between C and C++ is kinda obvious!
https://www.stroustrup.com/bs_faq.html#from-Smalltalk
> C++ got its Object-Oriented concepts from Smalltalk?
> No. C++ got the key notions of classes, derived classes, virtual functions (in other words, the notions of encapsulation, inheritance and polymorphism) from Simula just like Smalltalk did. In terms of family relationships, C++ and Smalltalk are siblings.
But I know at the University of Oslo there has been some annoyance that Simula’s place in programming history is so unknown while smalltalk has this outsized role.
Smalltalk definitely inspired Objective-C but C++ is clearly derived from Simula. As a fellow Scandinavian Bjarne was well aware of Simula and an active user of it.
Every time you write "protected" or "virtual", that's Simula speaking.
If you only are interested in "programming language design" this is not a bad idea. Changes and additions to a language often don't fit well into a language's overall design.
But after 1985.
Further, it's a bit counterproductive to just point out f"Hey, what about {some_lang}?"
Wikipedia has a decent resource to start, if you'd care to take a journey into computation notation history :)
https://en.wikipedia.org/wiki/History_of_programming_languag...
My own nitpick, to throw in the mix: The asterisk marks languages with ~sophisticated~ compilers, and I think that Ocaml being on the chart without one is absolutely ridiculous and shameful.
But who cares. It's just some guy's opinion as a chart.
It's been absolutely pummeled into stability by thousands of industrial use cases?
It's also like, STUPID fast. Try finding a large ocaml project, any will do, and see how fast it compiles.
Someone with more time and know-how could give a more technical testimony as to just exactly how badass ocaml actually is.
I am perfectly fine, if people take a controversial point of view, especially when entering a discussion. But then this should be the starting point for a discussion, not the ending point.
IMO, it's partly the ecosystem. There's regular Haskell, Haskell Platform, Cabal, Stack. It ends up being an alphabet soup of possibilities, and it's not clear what is depending on what.
And then there's monads, which are stumbling blocks.
State is allegedly the root of all evil. But I think the argument needs to be more nuanced than that: yes, state is difficult to reason about globally, but it's usually not so bad locally in small functions.
I think that this is what Rust gets wrong. It goes down the "state is evil" road, but there's really not that much wrong with the judicious use of mutated values.
If you really want to avoid mutability, then you're really going to need monads, something which seems a bad fit for Rust (based on what I see in Hackers News).
At the end of the day: fuggit, just use C++. It's fast, you can point in references to vars, and if you don't want them mutated, just make them const. That's the conclusion I drew a few years ago.
As Alan Kay might put it, most new languages are in the "pink plane": they're incremental improvements (sometimes a step back) on old ideas, and sometimes just inferior rehashes of them. None of them are what he calls "blue plane": revolutionary new ideas.
Kay seems to admire Erlang, though. What it brings to the table is the notion that a program can crash, and recover from it. That might be a "blue plane" idea.
I also assume he thinks Scratch is a blue plane idea; even though strictly speaking graphical languages are not new.
When I saw Ada couple of weeks ago, I noticed that it had the notion of tasks as a language primitive. I wonder if he'd consider that sufficiently blue plane.
Miracles are not awarded on merit, so when a language that got one is usable, it's like another miracle.
Global reasoning about state is hard, hence the assistance from borrow checker. Locally mutating local state in small function? Put a reference to vars, if you want them to be mutated, just make them mut. It's also as fast.
In a way, Rust does better job of localize/encapsulate mutation than functional/monad world.
Also, no asterisk (modern, mature compiler & runtime) for OCaml?
It's interesting to see this article on the front page at the same time as the Color Blindness article [1] discussing the difficulty of distinguishing tiny color spots. I'm not color blind, but I needed to zoom in on the first figure to see the difference between the red dot and the other red dot. Not to mention the black dot, the dark green dot that looks black at a distance, and the black dot that's actually an asterisk. Now I understand why these are so hard to distinguish.
I have great respect for Rich Hickey and I recently saw a cool talk about a financial startup using Clojure in production [1]. I have kept track of the language for some time but have never had the chance to use it in any serious capacity.
https://www.cs.toronto.edu/~gpenn/csc324/PLhistory.pdf
O'Reilly's History of Programming Languages
I would draw an arrow from Lisp to ML, since FP, GC, list processing etc. came from Lisp - ML was even implemented in Lisp and used the runtime.
Assembly was cool back in the day Z80, 68000... then C, but I felt too stupid to learn that stuff when I was a kid. Ugh. ;-)
What language would you recommend to someone trying to get into FP? I was considering Haskell but don't know enough about the ecosystem to make an educated choice for the language.
Fortran (especially modern Fortran) is quite well designed. PHP seems to be missing.
I hope Rust doesn't fade out, but honestly cannot expect otherwise. C++ has long needed serious competition, but has not had any.