1. 23
  1.  

  2. 5

    This is a good one. The other that I usually post with OP article is the Barnes guides that systematically show how it safely handles every aspect of programming that it can. Here’s the one for Ada 2012:

    http://www.adacore.com/uploads/technical-papers/SafeSecureAdav2015-covered.pdf

    1. 5

      It’s a shame there wasn’t more information on the tools Ada provides for concurrency - I haven’t seen another language which gives you as much flexibility and power to write safe concurrent code. It’s much more heavy weight than some other languages in some ways, but gives you very strong guarantees you don’t get elsewhere.

      It also would’ve been nice to talk a bit about some of the features which make it particularly well suited for embedded systems:

      • things like the ravenscare profile which give you a safe subset of the language using statically allocated never terminating threads
      • the ability to select the scheduling algorithm (including ones with task priorities which are used to avoid the possibility of deadlocks completely - see the priority ceiling protocol for more details)
      • the ability to address specific memory locations being built into the language, not just casting ints to pointers like you would in C
      • full control over how elements on records are laid out, including endianness, this is essential with the previous feature when you’re dealing with memory mapped IO registers for controlling hardware
      • the ability to define that certain data types can only be used at certain specific memory locations (see https://cs.anu.edu.au/courses/comp4330/Lectures/RTES-03%20Interfaces.01.pdf “pages” 314 - 332)

      For anyone who’s had to write code to interface with hardware on micro controllers, they’re probably wetting themselves with excitement by now, doing this in C relies on the compiler doing what you think it will, which there’s no guarantee of because the ability to use many of the features is implementation defined, if defined at all.

      ANU’s COMP4330, which these slides come from, is an excellent resource for learning more about both Ada and real time systems in general: https://cs.anu.edu.au/courses/comp4330/1-Lectures-Contents.html

      1. 2

        There’s a generic function in the standard library called Ada.Unchecked_Deallocation, which frees memory to the heap.

        A systems language without a safe resource finalization story is simply an unsafe language. This isn’t some fringe use case. Finalizing resources is a common operation in systems programming.

        Tasks are awesome, but sometimes they’re not quite what you want — particularly as there’s no protection against two tasks modifying the same variable at the same time.

        Now we know where goroutines come from!

        Scalar types can be constrained to a range. (snippet) The compiler will enforce the bounds at run time — out-of-bound values throw exceptions. (…)

        What if we want an operation to take at most a certain amount of time, rather than at least? We can do that as well, and now we’re beginning to get well out of C++ territory: (snippet)

        These things can be implemented entirely as library features in other languages. There is no need to bloat the core language.

        1. 6

          “A systems language without a safe resource finalization story is simply an unsafe language. This isn’t some fringe use case. Finalizing resources is a common operation in systems programming.”

          It wasn’t known how to handle the problem at compile time without a garbage collector when language was made. The main users of Ada do embedded and/or real-time systems where they allocate as much as possible in a static fashion. It wasn’t as big a deal to them. They should update it with something like Rust’s scheme, though. It would probably be easiest transition to borrow checker ever done since they’re used to programming in straight-jackets. ;)

          1. 6

            A systems language without a safe resource finalization story is simply an unsafe language. This isn’t some fringe use case. Finalizing resources is a common operation in systems programming.

            That comes off a little harsh.

            I think the more reasoned view is that sometimes in systems programming “unchecked” operations are inevitable, so a practical language will include a facility for doing so. Even Haskell has System.IO.Unsafe, for example, and most other languages have similar provisions.

            My experience using Ada was that most people do not use Ada.Unchecked_Deallocation. There is almost always a better way to do it, and that way will usually have several other advantages. The target market for Ada is embedded systems, safety critical software, (hard) real time systems, etc. and in most of those situations using anything “unchecked” is a big red flag, so it’s not typically used unless it’s really the only way to achieve what they need to interact with some library or piece of hardware, not “just because” like in C or C++.

            1. 3

              I think the more reasoned view is that sometimes in systems programming “unchecked” operations are inevitable, so a practical language will include a facility for doing so.

              Indeed, there’s nothing wrong with the occasional unsafe operation, especially if it’s a hidden implementation detail of a safe abstraction. But, other than resource-constrained environments where everything is statically allocated out of necessity, dynamic allocation is the norm in general-purpose programming, so it has to be done safely.

              1. 1

                On the contrary, dynamic allocation is the “norm” in most languages because those languages are designed around dynamic allocation and the common way they’re used promotes allocating. Ada is designed in such a way that the programmer doesn’t need dynamic allocation very often. In most cases it’s more straightforward (and obviously safer) to use static allocation or put things on the stack.

                I just grabbed “Software Engineering with Ada” off my shelf, and it’s 500 pages long and doesn’t even mention the unchecked functions.

                For example, in C++ the STL allocates all over the place, and a list or vector will grow forever. In Ada the popular data structure libraries will often require a size parameter when creating a vector or other structure. You don’t create a vector that grows forever, you create a vector that holds 100 elements and then it throws an exception if you add too much.

                I will admit I haven’t used Ada 2005 or Ada 2012, so it’s entirely possible that’s all changed, but the language used to be very much against dynamically allocating.

                1. 1

                  Even in that case, you need dynamic allocation. Suppose you want to use a vector of vectors, where “vector” is defined to hold up to 1000 elements in memory. If you statically allocate everything, you need to request enough space to hold 1000000 scalar elements upfront, no matter how many of those you are actually going to use. On the other hand, if you use dynamic allocation, each vector can be as large or as small as you need it to be.

                  And this is assuming that 1000 is a compile-time constant. If it isn’t, or if you use fancier data structures, then the case for dynamic allocation only grows stronger.

                  1. 2

                    That example doesn’t show why dynamic allocation is “needed”. If you don’t need 1000 vectors of 1000 elements declare the vectors to be smaller sizes.

                    This is kind of a silly argument at this point. I really don’t care if you have misconceptions about Ada or can’t live without dynamic allocation. Use something else. I was pointing out for the benefit of everybody else that in real life code the existence of Ada.Unchecked_Deallocation wasn’t as big of a deal as you made it sound.

          2. 2

            If you’re intrigued by Wirth-inspired languages and you want something more modern and more powerful, check out Nim - http://nim-lang.org/ .