I like the article overall but the continually repeated 'Language X didn't have that until <YEAR>' is very grating after the first ten or so.
I also wish there were concrete code examples. Show me what you are talking about rather than just telling me how great it is. Put some side by side comparisons!
Ada was also ignored because the typical compiler cost tens of thousands of dollars. No open source or free compiler existed during the decades where popular languages could be had for free.
Ada’s failure to escape its niche is overdetermined.
Given the sophistication of the language and the compiler technology of the day, there was no way Ada was going to run well on 1980’s microcomputers. Intel built the i432 “mainframe on a chip” with a bunch of Ada concepts baked into the hardware for performance, and it was still as slow as a dog.
And as we now know, microcomputers later ate the world, carrying along their C and assembly legacy for the better part of two decades, until they got fast enough and compiler technology got good enough that richer languages were plausible.
The origin of all sum types is in "Definition of new data types in ALGOL x", published by John McCarthy in October 1964, who introduced the keyword UNION for such types (he proposed "union" for sum types, "cartesian" for product types, and also operator overloading for custom types).
John McCarthy, the creator of LISP, had also many major contributions to ALGOL 60 and to its successors (e.g. he introduced recursive functions in ALGOL 60, which was a major difference between ALGOL 60 and most existing languages at that time, requiring the use of a stack for the local variables, while most previous languages used only statically-allocated variables).
The "union" of McCarthy and of the languages derived from his proposal is not the "union" of the C language, which has used the McCarthy keyword, but with the behavior of FORTRAN "EQUIVALENCE".
The concept of "union" as proposed by McCarthy was first implemented in the language ALGOL 68, then, as you mention, some functional languages, like Hope and Miranda, have used it extensively, with different syntactic variations.
Definitely if you don't have the C "union" user defined type you should use this keyword for your sum types. Many languages don't have this feature - which is an extremely sharp blade intended only for experts - and that's fine. You don't need an Abrams tank to take the kids to school, beginners should not learn to fly in the F-35A and the language for writing your CRUD app does not need C-style unions.
If Rust didn't have (C-style) unions then its enum should be named union instead. But it does, so they needed a different name. As we work our way through the rough edges of Rust maybe this will stick up more and annoy me, but given Rust 1.95 just finally stabilized core::range::RangeInclusive, the fix for the wonky wheel that is core::ops::RangeInclusive we're not going to get there any time soon.
The evidence is that the article’s writing is terrible. It repeats the same rhetorical devices over and over, dressing up a series of facts in false profundity, because there’s no actual authorial insight here. It’s just “write a well-researched article that demonstrates how ahead of its time the Ada language was” + matmul.
> JavaScript's module system — introduced in 2015, thirty-two years after Ada's — provides import and export but no mechanism for a type to have a specification whose representation is hidden from importers.
What?
#1 JavaScript doesn't have formal types. What does it even mean by "representation"?
#2 You can just define a variable and not export it. You can't import a variable that isn't exported.
There are several little LLM hallucinations like this throughout the article. It's distracting and annoying.
I really don't want this to be AI writing because I enjoyed it, but as other commenters have pointed out, the rate of publishing (according to the linked Twitter account) is very rapid. I'm worried that I can't tell.
Ada is a language that had a lot of useful features much earlier than any of the languages that are popular today, and some of those features are still missing from the languages easily available today.
In the beginning Ada has been criticized mainly for 2 reasons, it was claimed that it is too complex and it was criticized for being too verbose.
Today, the criticism about complexity seems naive, because many later languages have become much more complex than Ada, in many cases because they have started as simpler languages to which extra features have been added later, and because the need for such features had not been anticipated during the initial language design, adding them later was difficult, increasing the complexity of the updated language.
The criticism about verbosity is correct, but it could easily be solved by preserving the abstract Ada syntax and just replacing many tokens with less verbose symbols. This can easily be done with a source preprocessor, but this is avoided in most places, because then the source programs have a non-standard appearance.
It would have been good if the Ada standard had been updated to specify a standardized abbreviated syntax besides the classic syntax. This would not have been unusual, because several old languages have specified abbreviated and non-abbreviated syntactic alternatives, including languages like IBM PL/I or ALGOL 68. Even the language C had a more verbose syntactic alternative (with trigraphs), which has almost never been used, but nonetheless all C compilers had to support both the standard syntax and its trigraph alternative.
However, the real defect of Ada has been neither complexity nor verbosity, but expensive compilers and software tools, which have ensured its replacement by the free C/C++.
The so-called complexity of Ada has always been mitigated by the fact that besides its reference specification document, Ada always had a design rationale document accompanying the language specification. The rationale explained the reasons for the choices made when designing the language.
Such a rationale document would have been extremely useful for many other programming languages, which frequently include some obscure features whose purpose is not obvious, or which look like mistakes, even if sometimes there are good reasons for their existence.
When Ada was introduced, it was marketed as a language similar to Pascal. The reason is that at that time Pascal had become the language most frequently used for teaching programming in universities.
Fortunately the resemblances between Ada and Pascal are only superficial. In reality the Ada syntax and semantics are much more similar to earlier languages like ALGOL 68 and Xerox Mesa, which were languages far superior to Pascal.
The parent article mentions that Ada includes in the language specification the handling of concurrent tasks, instead of delegating such things to a system library (task = term used by IBM since 1964 for what now is normally called "thread", a term first used in 1966 in some Multics documents and popularized much later by the Mach operating system).
However, I do not believe that this is a valuable feature of Ada. You can indeed build any concurrent applications around the Ada mechanism of task "rendez-vous", but I think that this concept is a little too high-level.
It incorporates 2 lower level actions, and for the highest efficiency in implementations sometimes it may be necessary to have access to the lowest level actions. This means that sometimes using a system library for implementing the communication between concurrent threads may provide higher performance than the built-in Ada concurrency primitives.
Verbosity is a feature not a bug. Programming is a human activity and thus should use human language and avoid encoded forms that require decoding to understand. The use of abbreviations should be avoided as it obsfucates the meaning and purpose of code from a reader.
The programming community is strongly divided between those who believe that verbosity is a feature and not a bug and those who believe that verbosity is a bug and not a feature.
A reconciliation between these 2 camps appears impossible. Therefore I think that the ideal programming language should admit 2 equivalent representations, to satisfy both kinds of people.
The pro-verbose camp argues that they cannot remember many different symbols, so they prefer long texts using keywords resembling a natural language.
The anti-verbose camp, to which I belong, argues that they can remember mathematical symbols and other such symbols, and that for them it is much more important to see on a screen an amount of program as big as possible, to avoid the need of moving back and forth through the source text.
Both camps claim that what they support is the way to make the easiest to read source programs, and this must indeed be true for themselves.
So it seems that it is impossible to choose rules that can ensure the best readability for all program readers or maintainers.
My opinion is that source programs must not be stored and edited as text, but as abstract syntax trees. The program source editors and viewers should implement multiple kinds of views for the same source program, according to the taste of the user.
> Today, the criticism about complexity seems naive, because many later languages have become much more complex than Ada
I don’t think you really understand what you’re saying here. I have worked on an ada compiler for the best part of a decade. It’s one of the most complex languages there is, up there with C++ and C#, and probably rust
It's an intriguing idea. Having experience with software but almost none (only hobbyist) in hardware, I imagine it'd require a strong type system and mathematical foundation. Perhaps something like Agda, a language that is a proof assistant and theorem prover, with which one can write executable programs. https://en.wikipedia.org/wiki/Agda_(programming_language)
I wonder if an escape hatch like Rust's unsafe{} would be enough... a hardware{}. The real complexity likely lies in how to integrate the synthesis tools with the compiler and debugger. The timing model. A memory model like Rust's would certainly aid in assuring predictable behavior, but I'm not certain it would be sufficient.
There is none as far as affine types go, even is there is a parallel to be made with limited types, but they don’t serve the same purpose.
The way Ada generally solves the same problem is by allowing much more in terms of what you can give a stack lifetime to, return from a function, and pass by parameters to functions.
It also has the regular « smart pointer » mechanisms that C++ and Rust also have, also with relatively crappy ergonomics
AmbientTalk did this. I used it for a demo where I dragged a mp3 player's UI button to another machine, where pressing play would play it back on the originator's speakers. Proper actor programming in the veins of E and Erlang.
I wish more people knew about the Burroughs Large Systems[0] machines. I haven't written any code for them, but I got turned-on to them by a financial Customer who ran a ClearPath Series A MCP system (and later one of the NT-based Clearpath machines with the SCAMP processor on a card) back in the late 90s, and later by a fellow contractor who did ALGOL programming for Unisys in the mid-70s and early 80s. It seems like an architecture with an uncompromising attitude toward security, and an utterly parallel universe to what the rest of the industry is (except for, perhaps, the IBM AS/400, at least in the sense of being uncompromising on design ideals).
Wonderful article and a good fit with HN’s motto of “move slowly and preserve things” as opposed to Silicon Valley’s jingoistic “move fast and break things”.
It highlights the often perplexing human tendency to reinvent rather than reuse. Why do we, as a species, ignore hard-won experience and instead restart? In doing so, often making mistakes that could have been avoided if we’d taken the time or had the curiosity/humility to learn from others. This seems particularly prevalent in software: “standing on the feet of giants” is a default rather than exception.
That aside, the article was thoroughly educational and enjoyable. I came away with much-deepened insight and admiration for those involved in researching, designing and building the language. Resolved to find and read the referenced “steelman” and language design rationale papers.
> Why do we, as a species, ignore hard-won experience and instead restart?
Humanity moves from individual to society, not the reverse.
Some knowledge moves from the plural to the singular, top to bottom, but the regular existential mode is bottom-up, which point The Famous Article (TFA) makes in the context of programming languages.
Children and ideas grow from babe to adult. They do not spring full grown from the brow of Zeus other than in myth.
Thanks, that’s helpful. My wife is a teacher and talks about knowledge being recreated, not relearned: IOW it’s new to the learner even if known by the teacher. Hadn’t put those things together before.
Erm, well, the comment wasn’t AI generated, it was by me - a warts and all human. The sibling comments say TFA is AI generated and I’ll be the first to admit I didn’t spot that. Still found it interesting though.
I also wish there were concrete code examples. Show me what you are talking about rather than just telling me how great it is. Put some side by side comparisons!
I think that is the biggest factor of all.
Given the sophistication of the language and the compiler technology of the day, there was no way Ada was going to run well on 1980’s microcomputers. Intel built the i432 “mainframe on a chip” with a bunch of Ada concepts baked into the hardware for performance, and it was still as slow as a dog.
And as we now know, microcomputers later ate the world, carrying along their C and assembly legacy for the better part of two decades, until they got fast enough and compiler technology got good enough that richer languages were plausible.
https://xcancel.com/Iqiipi_Essays
There is no named public author. A truly amazing productivity for such a short time period and generously the author does not take any credit.
While true, that doesn't mean that other language's sum types originated in Ada. As [1] states,
> NPL and Hope are notable for being the first languages with call-by-pattern evaluation and algebraic data types
and a modern language like Haskell has origins in Hope (from 1980) through Miranda.
[1] https://en.wikipedia.org/wiki/Hope_(programming_language)
John McCarthy, the creator of LISP, had also many major contributions to ALGOL 60 and to its successors (e.g. he introduced recursive functions in ALGOL 60, which was a major difference between ALGOL 60 and most existing languages at that time, requiring the use of a stack for the local variables, while most previous languages used only statically-allocated variables).
The "union" of McCarthy and of the languages derived from his proposal is not the "union" of the C language, which has used the McCarthy keyword, but with the behavior of FORTRAN "EQUIVALENCE".
The concept of "union" as proposed by McCarthy was first implemented in the language ALGOL 68, then, as you mention, some functional languages, like Hope and Miranda, have used it extensively, with different syntactic variations.
If Rust didn't have (C-style) unions then its enum should be named union instead. But it does, so they needed a different name. As we work our way through the rough edges of Rust maybe this will stick up more and annoy me, but given Rust 1.95 just finally stabilized core::range::RangeInclusive, the fix for the wonky wheel that is core::ops::RangeInclusive we're not going to get there any time soon.
"These are not positions. They are proposals — structures through which a subject might be examined rather than verdicts about it."
The entire site is AI written.
What?
#1 JavaScript doesn't have formal types. What does it even mean by "representation"?
#2 You can just define a variable and not export it. You can't import a variable that isn't exported.
There are several little LLM hallucinations like this throughout the article. It's distracting and annoying.
In the beginning Ada has been criticized mainly for 2 reasons, it was claimed that it is too complex and it was criticized for being too verbose.
Today, the criticism about complexity seems naive, because many later languages have become much more complex than Ada, in many cases because they have started as simpler languages to which extra features have been added later, and because the need for such features had not been anticipated during the initial language design, adding them later was difficult, increasing the complexity of the updated language.
The criticism about verbosity is correct, but it could easily be solved by preserving the abstract Ada syntax and just replacing many tokens with less verbose symbols. This can easily be done with a source preprocessor, but this is avoided in most places, because then the source programs have a non-standard appearance.
It would have been good if the Ada standard had been updated to specify a standardized abbreviated syntax besides the classic syntax. This would not have been unusual, because several old languages have specified abbreviated and non-abbreviated syntactic alternatives, including languages like IBM PL/I or ALGOL 68. Even the language C had a more verbose syntactic alternative (with trigraphs), which has almost never been used, but nonetheless all C compilers had to support both the standard syntax and its trigraph alternative.
However, the real defect of Ada has been neither complexity nor verbosity, but expensive compilers and software tools, which have ensured its replacement by the free C/C++.
The so-called complexity of Ada has always been mitigated by the fact that besides its reference specification document, Ada always had a design rationale document accompanying the language specification. The rationale explained the reasons for the choices made when designing the language.
Such a rationale document would have been extremely useful for many other programming languages, which frequently include some obscure features whose purpose is not obvious, or which look like mistakes, even if sometimes there are good reasons for their existence.
When Ada was introduced, it was marketed as a language similar to Pascal. The reason is that at that time Pascal had become the language most frequently used for teaching programming in universities.
Fortunately the resemblances between Ada and Pascal are only superficial. In reality the Ada syntax and semantics are much more similar to earlier languages like ALGOL 68 and Xerox Mesa, which were languages far superior to Pascal.
The parent article mentions that Ada includes in the language specification the handling of concurrent tasks, instead of delegating such things to a system library (task = term used by IBM since 1964 for what now is normally called "thread", a term first used in 1966 in some Multics documents and popularized much later by the Mach operating system).
However, I do not believe that this is a valuable feature of Ada. You can indeed build any concurrent applications around the Ada mechanism of task "rendez-vous", but I think that this concept is a little too high-level.
It incorporates 2 lower level actions, and for the highest efficiency in implementations sometimes it may be necessary to have access to the lowest level actions. This means that sometimes using a system library for implementing the communication between concurrent threads may provide higher performance than the built-in Ada concurrency primitives.
A reconciliation between these 2 camps appears impossible. Therefore I think that the ideal programming language should admit 2 equivalent representations, to satisfy both kinds of people.
The pro-verbose camp argues that they cannot remember many different symbols, so they prefer long texts using keywords resembling a natural language.
The anti-verbose camp, to which I belong, argues that they can remember mathematical symbols and other such symbols, and that for them it is much more important to see on a screen an amount of program as big as possible, to avoid the need of moving back and forth through the source text.
Both camps claim that what they support is the way to make the easiest to read source programs, and this must indeed be true for themselves.
So it seems that it is impossible to choose rules that can ensure the best readability for all program readers or maintainers.
My opinion is that source programs must not be stored and edited as text, but as abstract syntax trees. The program source editors and viewers should implement multiple kinds of views for the same source program, according to the taste of the user.
I don’t think you really understand what you’re saying here. I have worked on an ada compiler for the best part of a decade. It’s one of the most complex languages there is, up there with C++ and C#, and probably rust
1: SPARK is a formally verifiable subset of Ada: https://en.wikipedia.org/wiki/SPARK_(programming_language)
2: https://arxiv.org/pdf/1805.05576
The way Ada generally solves the same problem is by allowing much more in terms of what you can give a stack lifetime to, return from a function, and pass by parameters to functions.
It also has the regular « smart pointer » mechanisms that C++ and Rust also have, also with relatively crappy ergonomics
https://learn.adacore.com/courses/advanced-ada/parts/resourc...
https://soft.vub.ac.be/amop/
CTM: https://en.wikipedia.org/wiki/Concepts,_Techniques,_and_Mode...
[0] https://en.wikipedia.org/wiki/Burroughs_Large_Systems
It highlights the often perplexing human tendency to reinvent rather than reuse. Why do we, as a species, ignore hard-won experience and instead restart? In doing so, often making mistakes that could have been avoided if we’d taken the time or had the curiosity/humility to learn from others. This seems particularly prevalent in software: “standing on the feet of giants” is a default rather than exception.
That aside, the article was thoroughly educational and enjoyable. I came away with much-deepened insight and admiration for those involved in researching, designing and building the language. Resolved to find and read the referenced “steelman” and language design rationale papers.
Humanity moves from individual to society, not the reverse.
Some knowledge moves from the plural to the singular, top to bottom, but the regular existential mode is bottom-up, which point The Famous Article (TFA) makes in the context of programming languages.
Children and ideas grow from babe to adult. They do not spring full grown from the brow of Zeus other than in myth.