Learning Ada
words.steveklabnik.com
words.steveklabnik.com
My mother (who found it amusing I was going to be coding Ada in 2008) gave me her old Ada books from the 80s (her employer at the time sent her to an actual course to learn the new DoD mandated language, back in the days when employers invested in their people), which I still have. I ended up programming in Ada up until 2012, when I managed to get a job using Java.
The language itself I rather liked (better than Java, for sure). It's the only language I've ever used that tended to produce programs that worked correctly on their first run (getting them to compile was the difficult part). The aerospace industry OTOH, I don't miss.
The fact that most employees don't invest in their people today, is egregious.
The fact that an employer like Boeing lets their developers "just pick it up on their own" doubly so.
And probably explains some of their quality issues.
At some point (1980s and 1990s in particular) things like retirement benefits started disappearing, replaced by 401k contributions and the like. Employees started moving more between companies so that long-term investment in employees became a problem. If I'm an employer and I spend 3 years getting you the equivalent of a graduate degree in software engineering (training on best practices, training in languages and design, attending conferences) and then you move, I have nothing to show for my effort.
You could add clauses requiring people to work for some period of time after receiving specific kind of training (like if you pay them for a degree) or requiring them to reimburse you if they leave early. But you can't do that for everything.
So companies have assumed that employees are mercenaries, and employees have become mercenaries. In the end, we still work 40+ hour weeks, but get worse compensation and companies refuse to invest in us.
They don't because the supply of workforce highly surpasses the demand, so it's easier to find another worker. In the domains, where it's not the case (mission critical software) things are different in general.
From my experience that is generally true with languages that have strong static type systems (like Haskell and Rust).
There isn't anything special about the first run, other than emotionally.
Also, if we define "run" as everything that happens when you feed that source program to the machine, then your first run actually bombed with compile errors.
You can't sit there pretending that the compile errors are the only mistakes you made, such that your first compile-error-free run that made it all the way to program startup and through to successful termination is also bug-free.
If you were that good, you wouldn't be making trivial errors flagged by a compiler.
One example would be loops and off-by-one errors. For the case of For-loops on arrays Ada's solution arguably does so via the type-system; in Ada arrays "know" their own length, start- and stop-index and these are query-able via attributes.
So, given Function Sum( Input : Integer_Array ) return Long_Long_Integer you could for-loop on the parameter, querying the 'Range attribute -- yielding a possible implementation of:
Function Sum( Input : Integer_Array ) return Long_Long_Integer is Begin Return Result : Long_Long_Integer := 0 do For Index in Input'Range loop Sum:= Sum + Long_Long_Integer( Input(Index) ); End Loop; end return; End Sum;
And the entire problem is avoided via the type-system.
They also encourage designing with types in order to enforce business logic, which is something you don't get in any of the dynamic languages.
Python doesn't force you to do those things if you dont need the reliability for a prototype or one-off code.
But if you want to make a reliable system, even convert your prototype into a reliable system, you can.
The aerospace industry OTOH, I don't miss.
At least three people ITT have said something similar to this. Can you elaborate about what is so bad about working as a software developer in the aerospace industry? Or would that require breaking all sorts of NDAs?You are treated as an interchangeable cog.
Most people who work outside the industry hear "I wrote a simulation model for a spacecraft attitude determination & control system" and think I was doing some really cool, challenging stuff. But as a software engineer, you really don't get to use your brain.
He was a pipefitter and he almost said what you just said word-for-word on a regular basis. If he had any corrections—well—he's just a lowly pipefitter, he can't be correct. Then he'd go out, work to their spec, the system would fail and he'd have to be called back in for overtime to fix it when they adjusted the spec to suit the problems he originally pointed out.
Nothing new under the sun, huh.
He was initially construction, and later maintenance on—well—all of the pipes.
So the situation wasn't as iterative. It was more, for ex:
* We need a new line for X process.
* Draft plans for new line.
* Receive [unwanted] feedback from fitters familiar with existing lines (having been in and out of them for n years)
* Disparage feedback and double-down on drafted plans
* Fitters implement plans
* Line fails (a number of times this step has nearly cost people their lives)
* Feedback of failure reverts to engineers
* Redraft plans with practical considerations applied
* Fitters implement fixed plans
AFAIU that even somewhat aligns with lean manufacturing—in that they adhered to the designed process according to the authority, and when defects were found they iterated.
I think the main complaint is that the fitters at this point act as almost an extension of the machine itself explaining why something will not work, and the given authority rejected any input at the outset—acting as the old priest caste, if you will.
I worked briefly for Toyota (subman. Toyoda Iron Works) and the process wasn't much different. The stakes were just lower as the parts were smaller, cheaper, and faster to adjust. If I, as an operator, attempted to raise issue with the engineering team I would have been laughed out of the room in the same way. †
† the engineering team had us set every M part aside for inspection 2-3 times a day so they could come check calibration. There was no other direct feedback loop that way from ops.
You aren't involved in the design or architecture (that is done several
levels above you by "System Engineers"), you are given a highly detailed
spec (sometimes so detailed it amounts to pseudo-code) that really doesn't
allow any room for creative problem solving.
Maybe there is something wrong with me, but it sounds amazing. Compared to
“Agile Enterprise Software Development” I have to do now, where specs are
non-existent, and developers are also architects, QA, DevOps, and managers, the
job that you've described is Heaven.I did an internship in college at a company that wrote avionics software, and it taught me that I didn't really want to do that. My job is actually a step beyond "agile enterprise software development" in ambiguity - I'm a founder, which means that not only are my specs non-existent, but my product, customers, and business model are too, and my job description also includes customer development, sales, marketing, interaction & visual design, and enough legal to avoid completely fucking things up. But I've found that I like the highly ambiguous environment where nothing's nailed down and everything's a problem that needs to be solved in a hacky way yesterday.
Luckily the economy is broad enough that people can move around to the work that suits them best. Take advantage of that - if you find you really don't like a sort of work, do something else!
This gave me a good chuckle!
There a few things I don't miss: 1) It can be a little stressful, knowing that your software is controlling things that if wrong could go bad (people's lives are at stake). The strong process we had makes you abstract that away, but still its serious work.
2) Yesterdays technology tomorrow. We were using stable releases from years ago on hardware I couldn't buy in a a language hardly anyone uses (we were an Ada/C shop). I do like Ada, but it made it harder for employees let go to find new work.
it was somewhat satisfying when the end result got built and it was operational.
My software probably running today, somewhere. Even though I left a while ago.
It's software work run by hardware companies. They don't schedule or budget or staff correctly. They often put engineers (of any sort) into decision making positions that should belong to computer scientists (or at least those trained in programming). Writing software is often treated as "just typing" when it's really an engineering and design activity.
Waterfall is also pervasive as a project management methodology. Even "modified Waterfall" (Vee model and others) are still subpar. What's frustrating is that, on the physical engineering side, they actually get the idea and value of prototypes and iterative development/design. But back to my first point, they still view software writing as a manufacturing activity, and not a design activity. So software shops get compared to the production line and not the engineering offices.
Regarding 2: Oh man, yeah. We've got people straight of school stuck on projects written in JOVIAL. Literally put them into a dead-end job straight out of school, we can't retain them. And we don't have the money (from customers) to hire the old timers, they're enjoying retirement too much.
Exactly this. I got stuck doing Ada near the beginning of my career. Took forever to extricate myself from that trap.
I've had the same experience with Rust. (Never used Ada/Spark myself.)
A related point is that training used to signify a ramp up time for an employee with an unfamiliar technology. Employees didn't go onto projects until they passed through a training course. Companies now expect zero ramp up time. Hence, they pass over highly qualified software engineers, who may not have a lot of experience in a particular technology, to get less experienced engineers who don't need training in the technology.
Working in SPARK Ada and Prolog early in my career taught me the importance of understanding what the "philosophy" of a language was in order to use it well. After far too much time spent trying to make them behave like a different language it clicks and then you get productive.
I think it's made me much more tolerant of new languages and more forgiving of my struggles when first learning them. Some times it can take a while to understand what idomatic programs look like in a new language, especially when it's a very differnt model to ones you have been used to.
At the time the programming language that became Ada was proposed, the Defense Department had somewhere around 700 programming languages being used in various projects. A project looking to add staff had very little chance of finding someone who knew the language being used. They had to hire an experienced programmer and expect that he would be able to get up to speed on the language being used in time to meet the (often unreasonable) deadlines. Ada was intended to replace many or most of those 700 programming languages. It sort of worked for a while. A lot of smart people worked on developing the language, and it was used in a lot of projects. The problem was that it never got wide adoption outside of defense contractor companies and aviation companies, and sometime back the Defense Department dropped the mandate that all new projects had to use Ada.
Ada is still being used in some fields, especially in some Defense Department projects, avionics and air traffic control, but it isn't in the TIOBE top 20 list of programming languages. Unless you're planning on making a career of working on defense projects, Ada probably isn't a language you should think about learning.
I guess it depends:
1. Ada, associated with SPARK, constitutes one of the most cutting edge technologies when it comes to automated proof for embedded code. This has encouraged some very cutting edge users such as NVIDIA to invest into Ada/SPARK (https://blog.adacore.com/nvidia-blogpost-announcement)
2. Learning a new language is always interesting. If you are interested in embedded programming in general, there are few languages more interesting than Ada today IMHO. I would probably tell somebody "Learn C/C++, Ada and Rust".
with Ada.Text_IO; use Ada.Text_IO;
procedure Outp is
procedure Foo (A : out Integer) is
begin
Put_Line (Integer'Image (A));
end Foo;
A : Integer := 12;
begin
Foo(A);
end Outp;
A clearer example would be: with Ada.Text_IO; use Ada.Text_IO;
procedure Outp is
procedure Foo (A : out Integer) is
begin
Put_Line (Integer'Image (A)); -- Uninitialized variable, random value
A := 42;
Put_Line (Integer'Image (A));
end Foo;
A : Integer := 12;
begin
Put_Line (Integer'Image (A));
Foo(A);
Put_Line (Integer'Image (A));
end Outp;
This will still give the uninitialized variable warning (typically can and should configure the compiler to turn that into an error, not a warning).Playing compiler, the output should be
12 -- Outp()
<random value> -- Foo()
42 -- Foo()
42 -- Outp()
You can make variables in and out by saying that (literally). This will do what Steve expected: with Ada.Text_IO; use Ada.Text_IO;
procedure Outp is
procedure Foo (A : in out Integer) is
begin
Put_Line (Integer'Image (A));
end Foo;
A : Integer := 12;
begin
Foo(A);
end Outp; with Ada.Text_IO; use Ada.Text_IO;
procedure Outp is
procedure Foo (A : in out Integer) is
begin
Put_Line (A'Image);
end;
A : Integer := 12;
begin
Foo (A);
end;I was told that adding the identifier to the end of blocks is just a good practice, since the compiler can tell you if you misread the nesting and wrote the wrong name.
On Twitter the other day, someone suggested that this is because, when Ada was first made, this kind of analysis was truly to expensive, and so the guarantee was not made, and they're sticking to backwards compatibility, and modern implementation should basically always warn. That seems reasonable, but I have no idea if it's correct. I assume most real-world Ada scenarios treat warnings as errors.
It was a great victory of Java and C# to require this. Java's analysis is "buggy" and C#'s is complete.
That is a bit of a theme in Java. The type inference often has the same problem.
(Although the type inference is also actually unsound)
Or like Go only taking into account C, Limbo, and CSP.
TLDR: reading uninitialized data in Ada is safer than in C.
Reading an uninitialized OUT argument is a bounded error, which is much less dramatic than C’s undefined behavior: the semantics is that you’ll read an arbitrary value (which is obviously bad as far an program intent is concerned), but otherwise the language constraints still hold.
This is very different from erroneous execution, which is very similar to the famous undefined behaviors in C, in which all bets are off and anything can happen.
It really shows how valuable having that very active and mature core library or managed package library is to a language. I did the same learning path as the prior poster but then just ended up stuck.
Since the university is known for its Areospace program, I guess that made sense to pick Ada as their primary language.
One of the things I'm a bit ticked about is that they moved the CompSci program from Aerospace to the School of Mines and Engineering. So, just as the drone era is starting they move CompSci to better align with other colleges. What a crock.
Still have my photocopied manual for BSD 2.9 on the PDP/11 - never imagined at the time that that Unix stuff would take over the world. Nice to have had that early exposure.
My early hate of Lisp was a direct result of them teaching it on the VAX. I was told the VAX had 4MBytes of actual memory and the each Lisp instance took 5. I played poker in the basement of Upson II while the damn thing loaded my program and played more while it ran. Being a lover of Forth at that point, tended to make me think Lisp was a bit of a hog.
Somehow the school got a Cray (I think from a oil company), but they weren't given the manuals right away. The manuals that they printed came from microfiche I had. I'm not sure if any students ever got to use it.
UND did give a unique experience in a CompSci degree.
Looking back, in the space of 3 years I got to work on quite a few completely different OSes (VSPC, VM/CMS, MS-DOS, VMS, Unix, whatever the Perkin-Elmer was) and languages (Pascal, 370 assembler, PL/I, Fortran, Lisp, Ada, C)
I wonder if kids nowadays get that kind of broad experience.
Wow, it is mind blowing to me that 450 different programming languages existed in the late 70's. Do we know what most of these were? Do most exist today or have they been lost to time?
[1] https://www.amazon.com/Programming-Languages-Fundamentals-Au...
Some surviving ones are NEWP and PL/S, if you happen to touch an IBM or Unisys mainframe.
With the risk of having my foot planted in my mouth, how "systems-ey" is Ada? Could I conceivably write an OS in nothing but Ada (and obviously a bit of assembly to kickstart it), similar to something like Redox-OS in Rust?
https://en.wikipedia.org/wiki/BiiN
https://apps.dtic.mil/dtic/tr/fulltext/u2/a340370.pdf
https://www.researchgate.net/publication/220713695_Specifica...
Note: This one is also downloadable on ACM or IEEE. I got it off of one of them. Has good example of Gypsy language for verifying systems.
https://cs.uwaterloo.ca/~Brecht/courses/702/Possible-Reading...
I suppose I'd have to do a big-ish project to know for sure how it compares to C as far as maintenance is concerned.
Ada compilers, versus Rust, used to cost a lot of money. Rust is novel so it doesn't have that historical baggage and reputation associated with it.
People view Ada as verbose (it is, I won't disagree), but it's not that cumbersome (in my experience). And reading it is a pleasure compared to reading a lot of other code. From a maintenance perspective, I greatly prefer it to C.
Static analysis tools and coding practices have made C and C++ safer languages than they used to be, even if they're not innately safe languages (or designed with safety in mind) as with Ada and Rust. So this mitigates the need (though drives up the costs if you want to do it right) to use a safer language in the fields that really care about safety.
AIUI, Ada toolchains have historically been commercial. GNAT was released in 1995, and i don't know how good it was, or is, compared to commercial versions.
From the history I've read, there was. Then at some point the US DoD the most vocal member, what created a very bad culture on the Ada community (based on waterfall methodologies and government contracts) that everybody learned to avoid.
[1] http://www.iuma.ulpgc.es/users/jmiranda/gnat-rts/node14.htm
Its been a while.
The ada runtime didn't have a lot of things built in so for our project we built a ada library that would call out to some C code that allowed ada to call to the OS for networking/shared memory/message queues and such. Sizing of types passed from ada to C was important, but wasn't too difficult. Ada also has a record type that seemed to map well to structs.
The existing ecosystem may have been pretty good, all things considered. Fast ramp-up, with eventual shift into supporting bytecode efficiently so any language can run.
Would you rather be coding around the inconsistencies in the SmallTalk implementations of Microsoft, Google and Mozilla, or just delivering a bytecode package of your code in whatever your favorite SmallTalk implementation (or any other language) is?
BASIC would be better than Javascript.
C would be better than Javascript.
Literally anything else, would have been better than Javascript.
http://archive.oreilly.com/pub/a/javascript/excerpts/javascr...
https://www.destroyallsoftware.com/talks/wat
http://www.javascriptgotchas.com/gotchas/common-javascript-e...
https://medium.com/javascript-non-grata/javascript-is-a-dysf...
https://whydoesitsuck.com/why-does-javascript-suck/
https://softwareengineeringdaily.com/2015/12/09/javascript-t...
http://blog.thefirehoseproject.com/posts/why-im-angry-at-peo...
Yeah, I don't think so. No matter how bad Javascript is, C would be way worse. Every problem of C ported to the web so all those bad practices that are mostly harmless because they are usually in simple programs with no network access when local program all of a sudden being entirely exposed.
http://blogopod.com/image/2014/javascript-comparison-table.p...
The software world could easily go without javascript and be a less toxic, buzzfilled, electron bloated swarm.
He is not trying to learn Ada.
I am trying to understand Ada better. I draw some comparisons to Rust because that’s one of the reasons why I’m reading about it in the first place: people ask questions comparing the two and I have no idea of the answers.
I spent much more than five minutes here, even though the writing is short; the learning website has a lot of stuff! As I said I’m the intro, this is mostly just a log of thoughts. But it was a good solid half-day of investigation. I’ll be doing more of it in the future, too.
And, since you're here, you probably have a typo: “GNATT” in the paragraph about threads should be “GNAT”.
Steve if you're around: there is an error I think in your post, you write
> Ranged integers are something people always say Rust is better at than Ada
And I think you meant the opposite ;)
Don't get me wrong - I'm not claiming the reference manual is a good learning source, for that I would recommend Barnes's book, but that it's an example of a language specification. Having precise specs is a minimum requirement for a safe language. Rust is too complicated as a C replacement but arguably a good C++ replacement. Unfortunately, it's not well-defined (yet) for writing safe programs. Without spec you cannot even tell compiler bugs from intended behaviour.
And yes, the lack of a spec is a weakness in Rust. We've been working on it for a while, and are gonna push it even harder this year.
> Without spec you cannot even tell compiler bugs from intended behaviour.
So this is true, but it's also a bit more subtle than that. For example, "there should be no undefined behavior in safe Rust" is a design principle that, while we don't have a spec, can say if something is a bug or not. (And we do have a few of those bugs.) This is, of course, not as good as a full spec, but guiding principles can really help.
Steve is most likely more familiar with Rust than any other language - which is why I would expect comparisons between it and Ada - but he doesn't go out of his way to insist on Rust's superiority.
If that interpretation comes across as negative, then I think you either must view most interactions with the world as negative or you've somehow managed to surround yourself with "yes" men...
Better late than never I guess.
There's also the difference between being familiar and knowing things in-depth; I was previously aware of the broad strokes of Ada and many of its features, but only at a high level. The point is to deepen this understanding.
(Also, I'm not on the language design team.)
I don't know why but after that talk I always assumed you played a role in some of the language design.
I mean, I think that's fair: usually, people who can speak deeply about the tradeoffs made for particular syntax or features are the people who were directly involved in making the decisions. I just read the discussions between all of those people. If we didn't have the RFC process, I wouldn't have so much context.
But yes, it's weird. First, he's not a designer of the language. Second, there are too many languages for anyone to be intimately familiar with all of them.
And third, there's just this weird bunch of very negative comments. What's up with that? You don't like Rust? (Not you, lukebitts, but the original commenter.) Fine. Don't use it. You don't like the publicity it's getting? You think your language is better? Languages are tools; they're not rock bands. Feel free to like and use yours. Rust doesn't take anything away from that. You don't like Steve? You think he's getting too much attention? He's getting it for useful, informative contributions. You want that kind of attention? Go and do likewise, rather than whining and sniping because someone else is getting attention.