It's not only a language that is key to success. Libraries. I searched for LDAP support for ADA (old protocol used by many companies). I found library (http://savannah.nongnu.org/projects/adaldap/) with latest news from 2002 and CVS repo :)
Then I search for SNMP (another dinosaur still in wildly use) - similar result.
Second - many solutions/libraries are purely commercial. You need basic open protocols support by default /free. Otherwise such great language will still be at it's niche.
Rust is on a good path to became XXI century successful Ada :)
This idea that Rust and Ada are somehow alternatives continually pops up, and I still don't understand it.
They each have their own ideas on what "safety" is, and how to address it. I'll admit I'm biased towards Ada, but I think it is pretty safe to say that "Rust safety" is a subset of "Ada safety" - but Rust does it's section and run further with it than Ada.
Rust is obsessed with memory safety. That's it's thing. Unsafe code aside, it's memory safe. And it tackles some concurrency issues too.
Ada is more concerned with overall correctness, particularly in terms of types, where the types are semantically meaningful. And it goes further and dips into memory safety and concurrency. It doesn't such an extreme tact as Rust, but it does an awful lot to provide good options that allow you to avoid many issues. And it generally tries to make programs easy to understand. And more - some of which, as the article notes, are really quite wonderful for going really low level.
Personally I see the most value in the semantic type safety. That's really been, in my own experience, where Ada has helped me the most. Many of the other features are also great. I just don't see almost any of it in Rust. You can sometimes get stronger guarantees about a few things and you kind of lose everything else.
How is that an alternative or a replacement? Yet this idea is everywhere.
I don't really understand the "Rust is obsessed with memory safety" meme.
When pitching Rust to others of course memory safety and thread safety get hyped a lot; because it's talking about something that most languages just can't do -- safety without compromise.
But actually ... memory safety is a small part of the reasons why I like Rust, and there are plenty of other cool bits in the language. It stands out a bit because it's different, but that doesn't make it the end-all goal.
Safety without compromise doesn't exist. Rust does what it does well, but at significant cost in developer time. I'd rather use a garbage collector, it's much much simpler and fine for 99.9% of use cases.
Garbage collection does make things easier, prettier, and simpler. BUT there are many problem domains in which a GC can not be used. A browser being a prime example...
Maybe you can find a better "prime example" than browsers, which nowadays are mostly known as execution engines for JavaScript, a garbage-collected language.
But frankly, I doubt that you can. Others will say "operating system kernels", but people are happily writing OS kernels in OCaml, so <shrug>.
Yet others will say "safety-critical hard real-time tiny microcontrollers without an MMU" (one of Ada's domains), but on those systems you don't want to do dynamic allocation anyway, so the question of GC or not is kind of moot.
I've said it before, I'll say it again: Rust would be a better language if it had a GC and the possibility of marking certain program parts as GC-free (the way it allows you to mark certain parts as unsafe).
That's kind of his point, you can't write a GC language interpreter in a GC language forever, eventually you need a non-GC language to actually implement the GC in. So in this way writing a Javascript executor in a GC language wouldn't really make sense, you're just adding needless layers of abstraction (at a serious performance cost). So I think a browser is an excellent example of an application which can't really be written in a GC language. Other examples might be Databases and realtime applications.
Anyway, even if you absolutely had to use a non-GC language to implement a GC, that would not preclude writing 99% of the browser in a GC language and only the GC in something else.
How do they compile/interpret PyPy's GC, is the compiler/interpreter written in a GC language? I said you can't do it forever, eventually you need to drop to a non-GC language (I feel very certain of this, so if I'm wrong I'd really like to know).
Also, why would implement GCs multiple times at different levels of abstraction in the stack, other than for something specific like PyPy which is specific like designing an interpreter to help test language features quickly?
PyPy is originally bootstrapped on the C Python interpreter, but it can then interpret and compile itself without relying on CPythob anymore. If you insist, then once PyPy is bootstrapped, the "drop to a non-GC language" is its process of having compiled the garbage collector's Python code to machine code.
But you're still wrong on this drop being necessary, I think. You can do it just fine in a language with GC that also allows you to allocate a block of memory that is not considered by the GC.
> But you're still wrong on this drop being necessary, I think. You can do it just fine in a language with GC that also allows you to allocate a block of memory that is not considered by the GC.
I think it's a bit disingenuous to say a "GC language compiled a GC language" when the compiler used non-GC portions of the language to do it. You're right, I should have said "A language which can work without a GC" instead of "a non-GC language;" but I think the spirit of my comment was clear.
That said I think what you said above is right, and non-GC code is really only necessary in the hot parts of an application (and applications that can't use dynamic allocation for whatever reason, but that's another discussion). Rust is even working on adding GC support [1] (albeit very slowly, as they should). That said non-GC languages (or at least the ability to write code that doesn't use a GC) is still necessary in many industries for many reasons; that isn't going to change for a long time, if ever.
Of course you need to drop to some sort of non GC language, or you would need a hardware GC. However look at Iota [0], that can compile LLVM to Common Lisp. So you can run GC and non GC languages within, kind of, Common Lisp. Or look at all the projects that compile a language to javascript, and there is no reason why the reverse could not be done.
When things such as the borrow checker are so heavily built in to the language, I find it hard to to see how Rust isn't ultimately intended to do memory safety. Obviously it does other things, and I'm sure it has some cool ideas in there. But I have a hard time seeing how it's a mischaracterization of Rust to say that memory safety is kind of it's thing.
I don't understand why the public marketing effort is so focused on safety, either, but it is. When I see Rust mentioned, e.g. here at HN, I cringe a little because odds are it's in the context of how unsafe everything else is, or there is at least some connection made to safety. "Obsession" seems loaded.
Rust is a very nice language with many useful and interesting features which may exist because of the developers' focus on safety but can very much be marketed without calling out safety all the time, and especially without the hints, suggestion, and innuendo that using a language without Rust's safety model is somehow dirty, dangerous, or worse irresponsible or unethical.
By "public marketing effort" do you mean "people talking about Rust"?
Personally, I interpret the focus on memory safety as a response to "memory issues aren't a big deal" or "memory issues only come from incompetence" viewpoints.
Again here the word "safety" starts to get rather muddy. What Rust calls safe is not what Ada calls safe. I'd rather be specific about what we're talking about.
Memory safety is not, itself, program correctness. It's just one way programs can go wrong.
I've always had a massive soft spot for Ada but I've never been able to find a use for it in actual work (not much call for it on the web).
I think the reason I like the language is the type system which is like the pascal one on steroids and I love Pascal, it was the language that taught me you could reason about a program by building up from primitives.
The issue there isn't the language, Ada is lovely but that the surrounding infrastructure isn't there, it lacks widely used 'modern' libraries for a lot of stuff you take for granted in .Net/Java (even PHP) Land.
I'd love to be able to use it at some point and writing a web framework on top of it has been one of those fun if I ever have lots of spare time projects that sits in my queue.
Ada was one of first, safer languages for system programming that also aimed to help with programming in the large, concurrency, maintainability, etc. Rust is the latest in that niche although without the embedded focus of Ada's common usage. So, of course we can compare them. Here's another on SPARK Ada vs Rust that's surprisingly fair from an AdaCore rep:
Of course you can compare them. I didn't mean we shouldn't ever look at the differences in how languages do things. We should. I meant I didn't understand how one could be seen as a replacement or straight alternative of the other. They have different goals.
And I've seen that before. Frankly I thought it overly nice to Rust by not spending any time at all considering the differences in user-defined types. That's really one of the biggest and most important differences to me, and a place I think Rust really falls short.
"I meant I didn't understand how one could be seen as a replacement or straight alternative of the other. They have different goals."
I agree. It's just a weird thing about these discussions that makes it necessary to bring up. The online forums typically divide between "system" languages you can write OS's or low-level code in versus "application" languages you write anything else in. Performance comes into play. GC vs non-GC, too. The kinds of benefits on safety and system side that people like about Rust are the categories Ada is designed to handle. It's behind on temporal safety but otherwise solid. So, we have to bring up the comparison due to how the local community might be mentally categorizing or evaluating things.
Also, many wanted something safer or better than C/C++ but never heard of Ada. That's worth addressing in and of itself. I think D language has a similar problem where it's a lot better than C++ in many ways but gets too little attention. Once upon a time, there were Delphi and Modula-3, too. Those times are past us. :(
One example is integer ranges; they'd be a runtime check in Rust right now. We'll get there. That said, in general, Rust's type safety stuff is fairly powerful, and IIRC has some things that Ada does not.
I do think your parent isn't fully right about the relationship though, as first they call Rust a "subset" of Ada's guarantees, but then say that Ada doesn't go so far as Rust in some places. In general, when discussing language semantics, I see them as more of a large overlap with some differences on each side, rather than one being a subset of the other.
first thing that comes to mind are bounds on integer subtypes. classic example is to declare an array to be indexed with such a type, then all out-of-bounds errors can be checked at compile time.
As as been mentioned, integer bounds for one. Using aspects in Ada will also let you provide other assurances (at compile time or runtime, depending).
Additionally, the "newtype" in Ada is far easier to work with. The new type inherits the operations of the parent type. When it comes to this sort of thing, it needs to be as simple and easy as possible or it just doesn't get done consistently.
> How does Ada address the problems that Rust's borrow checker addresses? Use-after-free in particular.
It has a more limited way of writing safe programs (memory pools and sub-pools, no aliasing by default, etc). That said, for some programs you will have to go unsafe and then you're done; however, from my limited experience with Rust it's also true there (Doubly linked list ?) even though you can go further and check more things.
Some people are working on having something similar in Ada/SPARK FWIW :)
> As for not being alternatives, how do they mix in the same project? Does Ada have C-compatible FFI that lets both Ada and Rust see each other as C?
Ada does have a C-compatible FFI, and in theory you can interface Rust and Ada. I don't know if it has been done though !
The general mindset is "if you need high integrity, you probably also need to statically determine an upper bound on memory usage." The consequence is that the safest Ada variants do not allow dynamic memory management at all.
But the next step down is to do the memory management in an isolated module of your code, which is then supposed to be vetted thoroughly.
Vanilla Ada (i.e. not the safest variant) does provide RAII for dynamic management of resources in general.
Ada addresses memory issues in a couple ways. In a general sense, the language is designed to prevent the need for explicit allocations and pointers as much as possible. The runtime uses a secondary stack to return dynamically-sized objects from functions. The low level parameter passing details are also compiler-controlled. The programmer specifies how an argument is used (input, output, or both) and the compiler deals with how to accomplish that. There are some other features (mostly related to types and bounds) that all combine to generally reduce the need for explicit memory management.
Once you do get to explicit memory management, Ada does a number of things. I'm going to a list here just for my own sanity.
First, all deallocations are essentially marked unsafe. You use Unchecked_Deallocation() to free memory.
More importantly, it provides memory pools, and subpools. Each pointer type can be associated with a pool (or subpool). Once the pool goes out of scope, all memory is freed. You can use this to avoid explicit deallocations yourself. Pools also control allocations and deallocations, and there exist Debug pools that can help ensure memory is accessed correctly.
Ada also requires that stack-based objects be declared as "aliased" before you may make a pointer to them, so it's always clear where there might be trouble.
Finally (I think), Ada has a concept of accessibility levels. Essentially a pointer cannot point to an object that is more deeply scoped than itself. This isn't the perfection of the Rust borrow checker, but it does quite a bit.
As for C FFI, Ada does that quite well. It's got a package in the standard library with C interface types, and aspects for marking things for C FFI.
Ada is so stable and backwards compatible that old libraries will work just fine, unless they have external dependencies or depend on things that change fast in the outside world.
For me personally Rust is not a good Ada replacement, because 1) it has the usual obscure syntax - maybe to attract C++ programmers, who seem to like obscurity -, 2.) many semantic tricks and borrower idiosyncrasies that makes it harder to write, read and maintain than idiomatic Ada, and 3) it's fast changing. The good thing about Ada is that it is self-documenting, it's almost impossible to intentionally or unintentionally obfuscate it, and once you've written a program it will continue to work 10-20 years later.
I think a lot of people would disagree with #1. There was a discussion on /r/technology yesterday where people were discussing how it was exactly the other way round – Ada has weird syntax (so many English words!) which slows adoption, and Rust is C-like enough that the target market of C/C++ users can pick it up, syntactically at least. I'm saying this having done a distributed systems course in Ada. It felt like writing a novel, about some very awkward people announcing every action as they did it. Rust, on the other hand, feels like pair programming with a wizard (the compiler) who knows how to write really great C++ and has many tips to share.
Rust's syntax is, like many new languages as they are invented, essentially a pick of the crop of the best syntax ideas from other languages. 'Best' is probably debatable but familiarity is certainly not. Type annotations are basically Scala syntax. Class::method(), ditching `return` in favour of last-line expressions and the || {} closure syntax are all pretty close to Ruby. Structs/enums are also basically Scala. `instance.method()`, and pretty much the rest of the language, is universal.
It's true, Scala syntax for types is the weirdest part, but once you know what it means it's not hard to decipher. Much easier than trying to figure out function pointers in C, if you ask me.
#2 is probably true, but that's the cost of staying close to the metal. Rust makes all your memory access very explicit, rather than bundling it up in the standard/GC or leaving it to you. But it's a model you can get used to, and it has value as a mental model aside from its application in Rust.
#3 – well. Ada was young once. Rust is incredibly stable for a project designed by a distributed community of Mozilla and a ton of volunteers.
How so? Scala class bodies are a mix of ordered constructor statements and unordered declarations/method definitions, while Rust structs can only declare fields (without any sort of initial value). Scala enumerations (both scala.Enumeration and the more common sealed class versions) look nothing like a Rust enum; if anything Rust enums look like ML/Haskell algebraic type definitions.
> It's true, Scala syntax for types is the weirdest part, but once you know what it means it's not hard to decipher.
The part of the type syntax that is like Scala (i.e. the colons and arrows) has its origins in the ML family IIRC. Rust's bootstrapping compiler was written in OCaml, so I suspect that was in fact the inspiration.
Ah, I see it's been a while since I've used Scala. I think I should have referred to case classes. Weak point nonetheless.
I did fail to mention the other very Scala thing: match expressions. Most complicated Rust match expressions could almost compile without errors in Scala.
Why? Ada libraries from 2002 without outside dependencies work perfectly fine. I'm using that old libraries all the time. Ada has been designed specifically for that, it's been used in the aviation industry that runs the same code for 20+ years minimum.
That you think otherwise only shows that you've never seriously used Ada in a larger project.
The last version of DOS also works really well for the things it was designed for. You still wouldn't start new projects targeting DOS if you could help it, even if it would satisfy your current requirements.
Well, we're talking a safe language. So, if want an archaic red herring, you'd be better bringing up Burroughs written in an Ada predecessor that was immune to most forms of code injection or crashes in 1961. If you want small and Ada, then Martes RTOS is one written in Ada that's still around. For small and secure, the Muen separation kernel can handle it.
Actually, I would, if my needs were simple enough. Rarely is it necessary to have much more in embedded fields. Have a look at MDOS, a modern reimplementation of DOS used in many modern embedded cases.
However, interfacing C code from Ada is a very straightforward process, where most types and procedures can be mapped automatically to corresponding Ada types. So if there exists a C library for the thing you want to do, you can easily use it from Ada.
Also, TLS support. Ada Web Server uses OpenSSL for that. It's not possible to develop a secure web application with ADA at this moment, because you can't run one of the known weak spots with ADA based implementation. If you can't do that, why bother at all...
I did consider doing all my projects using ADA. I really want to love ADA. I simply can't because some fundamental building blocks are missing. I am very disappointed over this.
Here is my list of shortcomings when it comes to Ada
1) Ada is not a magic bullet, the seminal case study of why computer bugs are bad taught in CS courses around the world is the failed 1996 Ariane 5 rocket launch where the rocket veered off course and then exploded due to a software error that caused it not to understand the data it was getting from a sensor. More recently there are plenty of demonstrations of poor security in commercial plane avionics systems.
2) Ada is not easy to write, it's around the level of C I grant you, but it is not easy by any means, more importantly it is complex not simple. Each of those "features" like assert adds a layer of complexity to the system making it far harder for the programmer to write for. I think we all agree if we could program with simple functions that each do one thing and one thing well then combine those functions makes for a much simpler language and easier to think about.
3) Overhead, each of these features like assert adds a lot of overhead into the system, this is just not viable in a lot of systems, whats more those features are optional, so it is the first thing to drop where possible.
4) Toolchain and library support, most of us can't afford expensive toolchains and libraries, we don't work for very rich government contractors. Also we need libraries and toolchains are well maintained. Java has a massive standard library and a lot of free 3rd party libraries available, C/C++, python, perl, ruby, rust, javascript, c#, clojure... are all similar in that they have well maintained tool chains and good library support freely available either directly by language authors or from a third party.
>I think we all agree if we could program with simple functions that each do one thing and one thing well then combine those functions makes for a much simpler language and easier to think about.
Well, I don't agree. You could end up with tons of small functions, and complex interactions between them (whether they are pure or not) than make for spaghetti logic.
I also don't see how Ada's pre/post conditions make it more difficult to program. More tedious, maybe, but about as much as writing tests. Not more difficult as in conceptually more challenging.
As for the Ariane error, Ada could have prevented it, if it was left to -- but the programmers didn't let it. It's not a silver bullet of course, but nothing is, not even formally proven programs.
Finally, the overhead is true, but some domains don't need much speed anyway, and for others, you could always have the checks for all demo/dev runs and drop them for the final production output.
> You could end up with tons of small functions, and complex interactions between them (whether they are pure or not) than make for spaghetti logic.
I think 'one thing well' is pretty much the opposite of this idea. It implies encapsulation and composition, not smushing together. If some functions are pure, there is no such thing as 'complex interactions between them', only simple ones.
On the other hand, it would definitely be weird if Ada were used as a functional programming language.
Not all things can be expressed by simple interactions between simple functions. A program doing complex tasks composed of pure functions will be either wide (fewer functions but having many parameters) or tall (long string of functions with few parameters).
I do not believe that a simple paradigm shift will help you create arbitrarily complex programs simply. At some point the complexity must be handled.
1) and 3) are related as far as I remember - Ada WOULD have found the problem which was responsible for the Ariane 5 launch failure, but the section involved was speed critical, so the asserts were dropped to make the code run fast enough.
Sad reality: The best security features in the world are useless if they are too slow for your use case.
Ironically, it's also Ada's asserts which contributed to the failure (though far from the root cause): The result of the erroneous calculation wasn't actually used, so just ignoring it like C would have would have been fine. It was the fact that the wrong cast caused the software to abort which resulted in the crash.
This is why static checking is better than runtime checking.
Rust has some, but not enough. What is needed is something like Isabelle sledgehammer, quickcheck and metis logic and higher function correctness checkers. (Yes, Haskell has a bit more primitive version of Quickcheck.)
A smaller less featured one, but very useful nonetheless. (Specifically, sledgehammer is superior as a checker and automated proof library check is also invaluable in simplification.)
Technically, Why3 (intermediate language and prover manager used in SPARK for verification) can interface with Isabelle too. I should try it out.
More edit: someone has done it, called HOL-SPARK. Excellent.
It was actually an engineering error. The software in question was designed for Ariane 4, and the condition that happened in Ariane 5 could not occur. But a shortcut was taken, and the suitability of the software was not reassessed. Then Ada's exception mechanism was pulled into play when it never should have been given the requirements of the Ariane 4.
A Denial of Service vulnerability is a security vulnerability no matter the cause. That COULD be an attacker, but it could also be that your code runs too slowly or the UI is too hard to learn.
I feel like I have to rule out some misconceptions and defend Ada a bit, even though I don't use it very often any longer.
Ada is not a magic bullet
1) Nothing is a magic bullet. (And certainly no actual user of Ada has ever claimed that it is a magic bullet.)
Ada is not easy to write, it's around the level of C I grant you.
2) Ada is way harder to write than C, unless you're very proficient with it, of course. It's a much bigger language, and the syntax is not easy. Ada is designed for easy readability and maintainability, not for easy writing. It also requires a lot of repetition if you write good style. (You can write Ada code like C and Pascal, but then you loose most of the language's main advantages.)
Overhead, each of these features like assert adds a lot of overhead into the system, this is just not viable in a lot of systems.
3.) Ada is blazingly fast even without any optimization, and after optimization basically around the performance of C (or C++, if you use tagged types with dynamic dispatch). That's not very surprising, since GNAT uses gcc's backend optimizations. As for overhead, every runtime-check in Ada can be switched off. You can even discard the whole runtime system and use your own minimal runtime system, if you feel ambitious.
There is reason to believe that future versions of Rust (or even the current compiler) are faster than idiomatic, well-styled Ada. The goal of Ada was never to produce the fastest executables, and the fact that GNAT creates so fast ones is merely due to the authors of GCC and Ada's strong focus on compile-time operations and checks that it shares with Rust.)
Toolchain and library support, most of us can't afford expensive toolchains and libraries
4) Absolutely true, library support is not comparable to C and not even remotely comparable to C++. However, see my other remark here, an Ada library that appears to be abandoned will compile and work 100% fine and you can understand it by reading the source code (no documentation needed). But yeah, there are way less libraries, of course.
As for Java or Python, these are bad comparisons. They are both much slower than Ada and way less maintainable.
In regards to level of ease of writing, I'm assuming some level of competency in the languages we are talking about, all languages have a learning curve.
In regards to speed as other comments have also pointed out some of the asserts were optimised out of some of the Ariane 5 code, while the ones left in worked towards the cause of the issue ;)
The reason Java is in there is due to the libraries available, you can use those libraries with other JVM hosted languages like clojure ;) now tell me it's not maintainable. Similar reasons why python is in that list, I believe no OOP language is truly maintainable at this point, it adds to much complexity.
Ada ticks a fair amount of the boxes in the "Interesting statically compiled languages by wishlist features" google doc, which I started, and had some crowd-sourcing help to fill in:
I had a strange internship topics involving Ada. I tried to run a huge program (a simple stdio wrapper around a huge library actually) on an Android machine (Android 2.3, ARM). At that time, the only ADA compiler for ARM was available on BSD so I had used a Windows machine for development and a OpenBSD laptop for compiling the wrapper.
The subtyping feature I love the most. You see the benefit when you need to call a function which is taking many numeric arguments, all of them is a subtype so you can't give the arguments in the wrong order (latitude and longitude for example).
Important terminology nit: subtypes and derived types are two different things in Ada. A "subtype" is essentially a local new name for an existing type (it makes little sense to export subtypes). A derived type is a new type that is based on another type, but can be restricted to a subset of values of the original type, and cannot be interchanged with the original type.
I only have very little experience with Ada, but being able to define a type whose values are integers in the range, say, 1 .. 7, to represent days of a week was an eye opener.
Range types are probably the main thing I miss from the Rust type system.
But even without range constraints, wrapper types (called newtypes in Haskell and Rust) are great. Let's say you have a function that accepts a temperature. A temperature is a float, but you want to prevent the user from mixing up celsius and fahrenheit.
It will fail to compile if you accidentally pass a Fahrenheit value to `print_celsius`, but at compile time all values are optimized down to plain floats, without any runtime cost.
More programming languages should adopt this concept :)
Whether any compiler "cleans this up" depends in the system's ABI; parameter calling conventions are not up to the compiler to decide (unless it can prove that a given function cannot be called from code it does not control).
That said, yes, modern ABIs for modern machines usually pass single-element structures of primitive types in registers of the appropriate type. x86 (32-bit) is not modern in this sense: depending on the exact ABI used, these structures might well be passed on the stack or in an integer register.
Yeah, C and Rust work the same way here (as far as I can tell). Rust can also define type aliases (with the 'type' keyword) but they're not new types much like C typedefs.
The only advantage of Rust in this case is that its tuple syntax can be a bit nicer than C structs and the language supports overloading so that you can reimplement the comparison operators for instance (or do more complicated things, for instance if you have a "decibel" type that must have a special addition implementation)
One of my favorite features of Scala that Java is missing is Scala's newtype-like functionality. It lets you define types which get erased to another one the JVM level (so there's no unnecessary boxing) but are checked in Scala and can hide their interior type and provide different methods.
Huh. That's clever. This approach should also work in other languages, say, C/C++/C#. I don't remember if C uses structural identity for struct types, but it might work.
No identity or equality concept in C for structs apart from their address, I'm afraid. In C++ one can define a comparison operator, but it has to be implemented manually.
Not that you can use the language-provided == on floats anyway, due to precision issues you should always check if the difference is below a specified limit...
> Not that you can use the language-provided == on floats anyway, due to precision issues you should always check if the difference is below a specified limit...
Hehe, I've been there. ;-) Fortunately, that code dealt with physical coordinates, so if two points were less than 100µm apart, they were equal for our purposes.
I worked with Ada for several years on a military satellite program (simulator software for various satellite subsystems). Specifically, I was using Ada95 on SPARC/Solaris, and later got to work on a project (with a different employer) to port much of the same system to x86/Linux with Ada2005 (so many endian issues :shudder:). This was in the mid-late 2000s.
I remember when I told my mother (also a software engineer) that I got a job using Ada, she laughed and handed me all of her old Ada83 books (which are still on my bookshelf at work). I'm doing backend services in JVM-land these days, which I enjoy a bit more (not to mention I'm building a more portable skill-set) :)
"Code should be easy to write, easy to read, easy to maintain, and most importantly, it should be reliable". Ada is not easy to write. Perl is easy to write (but not easy to read or maintain).
When I was student, Ada was the main language at my school. It was used the first year to teach algorithms and the second year to teach parallelism. During the first year, I have also learned C by myself for curiosity. After the summer holidays between first and second year, I had forgotten most of the syntax needed to start a new program in Ada, but I was remembering perfectly well how to code in C.
Even After 8 years of usage of Ada, I still needed the user manual regularly. After less than 1 year of usage of C, I could sell my R&K.
How would you rate your young self on the "hello-my-name-is-scale", as I like of to think of Stroustrup's notes in his short article from 1999[1] -- in C and Ada at the time? Would your C code "blow up" differently from your Ada code, do you think?
I'm not much of a fan of C++ myself, but I often find myself looking back at that short note, as a pretty valid criticism of how C tend to mix some parts that appear simple with some very complex actual behavior (eg: printing strings, reading in strings and integers).
Does someone have experience with Ada 2012s Design By Contract support (including tooling, preferably for GNAT)?
Eiffel is yet another Pascal-ish language whose passing I lament, and lately I've been seriously considering giving Ada another try, given that Modula-3 and Oberon won't exactly come back to life miraculously, and I'm still a bit dubious about all the new kids on the block.
It's such a pity these days there is no modern tool chain/workflow for Ada (or C++ for that matter). I mean, a package manager, a build tool with integrated dependencies. As far as I know, there is very little open source software for Ada. It's a shame, because I feel like the language would become more mainstream, if only better tooling was easily available.
I believe you are looking for http://conan.io + cmake + any number of IDEs (VS, QtCreator, CLion, KDevelop, Eclipse, Vim) all of which will integrate with cmake perfectly.
I'm sure I'm not the only one that would appreciate an up-to-date, real-world best-practices "How I start"[1]-article for Ada - from people that actually write non-trivial Ada code and have a stake in project setup, packaging etc.
For C++, I'm reasonably happy with CMake and the Jetbrains CLion IDE.
CMake makes it relatively painless to wrap multi-platform dependencies without having to explicitly know whether they come from a Unix package manager or from Windows DLLs.
The problem is that it does not manage and version dependencies for you. Say I start a new C++ project where I want - say - use ZeroMQ and also Folly to parse JSON. Where do I start? Should I install ZeroMQ and its headers globally? What if the version changes? Will it conflict with other system libraries? Well, better start using Docker. What if the version I need is not in the Ubuntu repositories yet? I need to add to the dockerfile instructions to download and install the dependencies... you see, things get out of hand real fast
"Some people, when confronted with a dependency problem, think 'I know, I'll use Docker.' Now they have two problems."
Unfortunately there's no single answer. Static libraries vs. dynamic? Global install or packages from a repo? Everything depends on the degree of control you have over the deployment environment.
Yeah, I know, I don't want to use docker. The problem is that C and C++ offer no real option in this camp. I'd be happy with anything that resolves and download dependencies, builds them locally (using CMake?) and adds the correct headers and library dir configurations to my project. But I could not find anything that really works
True, C/C++ have it a bit more complex. But is it really an unsolvable problem? One would think that with the level of investment in C/C++ someone would be able to create something all the hipster languages have done in the last 20 years.
I guess Gentoo's emerge would be the closest thing to a "good" C/C++ package manager we have today, which I find a bit funny :)
You can do this with http://Conan.io and CMake. It is quite young still, but at this point is fairly feature complete and doesn't have any breaking changes anymore.
I wish there were a simplified (as in automated) and "community-blessed" workflow at least for static binaries with source dependencies, like all the popular "modern" PLs are doing these days. I'm saying this as a newcomer (in C++ land) that finds the lack of this kind of tooling a bit intimidating.
I know what you mean. It's just really hard to bolt dependency management on C family languages, and so many ways it can exacerbate the problem by adding another layer of accidental complexity... (IMHO, CocoaPods is a good example of how a community-managed library dependency manager can end up creating a worse mess than the one it tried to solve.)
The Rust team started working on a package manager early as part of the language design, which seems like the only way to make it actually work.
I wanted to use Ada for a personal project, it's not what it's cracked to be. Some registers are hard to map in the language.
The timing side of things is extremely misleading: there are time primitives in the language, but you don't know if the implementation of the runtime will actually reach your constraint, and you won't be warned (it took me 2 days on the scope before understanding that it was not my code that was the issue).
Ada as an ecosystem has it's own alternative, SPARK. It's not a dependently typed language, but you can go just as far with it using pre and post conditions, and ghost code, insofar as what you can prove.
It's also used in other embedded systems. Based on public talks, Thales (https://en.wikipedia.org/wiki/Thales_Group) seems to be using it a lot internally, and not everything they do is military.
On early PCs, Pascal and C were pretty much tied in popularity. Both were free to implement, and small enough that you could make a fast compiler on a typical PC with only 256-640 kB RAM.
C won because it was more flexible and was chosen by Microsoft, but Pascal definitely had a strong following (it was the original Mac's API language, and on PC it was a major contender thanks to the nice and fast Turbo Pascal IDE).
Ada was a complicated and rigid language designed by a Department of Defense committee. That was not great PR for those early individualist PC users. (Who wants to program in the language of "The Man"?)
If Pascal was a Cessna and C was a Learjet, then Ada was the F-35 -- complex, expensive, late.
> Ada was a complicated and rigid language designed by a Department of Defense committee
Ada was designed by Jean Ichbiah, and although there was a committee he did override them on multiple occasions. So not really a design-by-committee.
The reasons it got no traction were: it was too complex/heavyweight, and too dissimilar to C to warrant a change (businesses waited for C++ instead, since it was around the corner at that time); due to its complexity it took a while for certified compilers to show up, and when they did they were quite expensive.
Since it was properly established in high margin markets, the community (mainly AdaCore, since they are the main compiler vendor) did little to improve its standing -- the only open-source projects they have pushed are all under GPLv3, which is not going to help with its popularity (not a judgement on GPLv3, it's just that basic lib are almost always under more liberal licenses, e.g. Boost). It really feels as if these OSS projects were pushed only to attract new programmers, while trying to prevent[1] an actual independent community from springing up. Odd behaviour. Every 6 months or so someone on HN or Reddit posts an Ada article that get people's interest, and then they discover they cannot write their project with it due to its licensing.
Ada is a beautiful language, but the licensing issues, the archaic and bloated IDE tooling combined with the proliferation of ancient bitrotting libraries are crippling Ada's potential.
Drake [1] is a promising new Ada runtime with non-GPL license that deserves more support.
Similarly, DRACO is ISC licensed [2].
Of course, these projects aren't backed by moneyed interests like AdaCore is, so they get no love.
On the other hand, C++ has become fairly popular, and IMHO it is at least as complex as Ada, with Ada being more readable and harder to use as a foot-seeking shotgun.
I remember reading about a (compiler-checked) subset of Ada for deterministic realtime code. If I was writing code that had to meet hard realtime requirements, I would certainly love it if the compiler could help me with that.
The sad part is that it turned out that Ada compilers were actually easier to implement than C++ ones.
And while we can do Ada style programming in C++, the lack of control over the C copy-paste compatibility features hinders that, unless one is allowed to turn all security knobs on (warnings as errors, sanitizers, code guidelines compliance).
I almost said Javascript out of ubiquity, but it'd be a grave insult to the plane. Java is a good answer, maybe C#, maybe Python. The language needs to be one that gets a lot of work done, and is reliable.
What's a language that's just always got your back in a situation? That's the F/A18.
Was anyone building things like operating systems or drivers in pascal? AFAIK that was always the realm of c. Turbo pascal was the first language I was taught, I have a soft spot for it but I think it had largely faded away by then.
Yeah, when I was working at Burroughs in 1980, they were doing printer drivers and a distributed OS prototype in their version of Pascal. Problem was, everyone needed to beef up Pascal in their own way to make it industrial level.
It depends on which compiler you use. Assuming you use GNAT, the compiler is written in Ada and the backend is gcc, and you have the same optimization options as C in gcc.
I'd say its performance is usually in the range of C++ performance. You can make it as fast as C, of course, because nobody forces you to do object-oriented programming (tagged types in Ada) and all runtime checks can be switched off with pragmas. However, I don't think that many Ada programmers are interested in that.
In a nutshell, speed is not a reason to opt for Ada over C. Safety and maintainability are. As for reasons for going the other way, there are plenty of them. Getting Ada programs to compile can take a long time, especially when you're learning the language, and the learning curve is relatively steep. Ada is a huge language in comparison to C and it's syntax is "per-construct" - it looks easy but there is a lot more to learn in comparison to, say, Pascal. Another reason: Lack of external libraries. C has way more.
I wrote one simple but computation-heavy toy program in Ada (check the Goldbach conjecture), and performance was about as good as my C and C++ versions.
Although I am not sure if that counts as read world usage. ;-)
In theory, it's just as fast as C/C++, when you compare GNAT against GCC/G++.
In practice, some language constructs are not as optimized as their C++ counterpart.
The end result is that you can expect the Ada 83 subset to be extremely fast, but more recent constructs like OO and controlled types (equivalent to C++ virtual destructors) to be slower.
All in all it has a pretty good performance story !
> In theory, it's just as fast as C/C++, when you compare GNAT against GCC/G++.
Is this the same theory that makes java is just as fast? Ie, if I wrote idiomatic Ada would the levels of indirection (pointers to pointers to pointers and virtual functions everywhere) by more like c or more like java?
Well, yes and no :) Ada is very close to C++ in terms of runtime abstraction, unlike Java, so it's not relying so much on the "sufficiently smart compiler" fallacy.
Also, there are several idiomatic dialects of Ada, because Ada has a facility to deactivate language features at compile time. Some people in safety critical don't want any dispatch for example.
FWIW I ported a quite large code base from C++ to Ada so I'm have first hand experience with this.
Or much smarter than you, but wanted to show the examples with syntax highlighting but couldn't be bothered to get some editor that exports as HTML or some plugin (both of which might not even be allowed/quick to install on the CMS they use).
As for the extra compression, they could just not care as the text is still visible enough, it's not supposed to be a textbook, and it's small and loads fast.
I get emails all the time where people use word or powerpoint documents with just one single image pasted inside, instead of attaching it to the email or sending it in HTML format.
A brain surgeon might be excused, but not the guys from customer's IT department or other fellow developers in offshored teams, they should know better.
Puppy 1: And so, in conclusion, we have determined that Ada provides sufficient safety guarantees and features for our embedded system needs. Any questions?
Puppy 2: Yes, I have a question. Why didn't you use Rust?
Puppy 1: That's a good question. While Rust looks promising, we felt it was too immature for our needs and decided to go with the time-tested, standardized semantics and extensive tooling available with Ada.
Puppy 2: Rust has a borrow checker. That makes it 100% safe.
Puppy 1: Leaving aside the fact that no language is 100% safe, safety is a complicated topic and you can't make strong statements like that about it. Does Rust's borrow checker enforce arbitrary program invariants?
Puppy 2: ...Rust has a borrow checker. That makes it safe. Borrow semantics is the secret ingredient in the memory safety sauce.
You do realize that that wasn't intended to be a serious argument about the points of Ada vs. Rust... right? Have you seen "MongoDB is web scale" (https://youtu.be/b2F-DItXtZs)?
Second - many solutions/libraries are purely commercial. You need basic open protocols support by default /free. Otherwise such great language will still be at it's niche.
Rust is on a good path to became XXI century successful Ada :)