Ada is an old programming language created to enforce "safe" programming.
It is best known for tiny accident when such a "safe" Ada program blew up Ariane 5 rocket in 1996, costing approximately $370m.
If we take ratio of losses due to programming language issues to number of people coding in a given language, Ada would likely rank as the absolute least safe of all languages. Sure, SQL injections cost $billions, but SQL is used by 10000x as many people as Ada, so an average SQL programmer is doing a lot less damage than an average Ada programmer. If that doesn't prove that TDD is more important than "static safety", then I don't know what will.
Also, as an old language Ada is fairly difficult to run on modern operating systems, so we'll be using Docker to run it.
It is named after Ada Lovelace, who is often called a "first programmer", which is a considerable exaggeration, but let's leave all that historical stuff behind and explore the language itself.
Let's start with
with Ada.Text_IO; procedure Hello_World is begin Ada.Text_IO.Put_Line("Hello, World!"); end Hello_World;
As I couldn't find any compiler running on OSX, we'll run it with Docker:
$ docker run --rm -i -t -v $(pwd):/source nacyot/ada-gnat:apt gnatmake hello_world.adb gcc-4.6 -c hello_world.adb gnatbind -x hello_world.ali gnatlink hello_world.ali $ docker run --rm -i -t -v $(pwd):/source nacyot/ada-gnat:apt ./hello_world Hello, World!
One thing that's already notable is
end Hello_World. Yes, Ada, for "safety" reasons, requires every
end to specify what it's ending. I know it sounds like a joke, but people who created Ada were absolutely serious about it. In some cases you're allowed to skip saying what you're ending, but we're trying to write Ada the way it was meant to be written.
Here's Fibonacci in Ada:
with Ada.Text_IO; procedure Fibonacci is function Fib(I: Integer) return Integer is begin if I <= 2 then return 1; else return Fib(I-1) + Fib(I-2); end if; end Fib; begin for I in 1..20 loop Ada.Text_IO.Put_Line(Integer'Image(Fib(I))); end loop; end Fibonacci;
Let's run it:
$ docker run --rm -i -t -v $(pwd):/source nacyot/ada-gnat:apt gnatmake fibonacci.adb gcc-4.6 -c fibonacci.adb gnatbind -x fibonacci.ali gnatlink fibonacci.ali $ docker run --rm -i -t -v $(pwd):/source nacyot/ada-gnat:apt ./fibonacci 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765
There's a lot to unpack here:
- where's those extra spaces coming from? Ada thinks it's unsafe to convert
"7". In some weird idea of consistently since
-7, 7 converts to
7with extra space where plus/minus sign would go.
- at least Ada has loops over ranges like
for I in 1..20 loop, it's baffling people make languages even today which don't have that
Integer'Imagesyntax for function in a package looks really weird, especially since we also have more familiar
.on the same line.
And finally we get to the FizzBuzz, and it's surprisingly convoluted in Ada. We need to strip that extra space. Well, surely Ada would have strings in its standard library, right? You wish. It its drive for "safety", it provides fixed-width strings only.
So you can do this:
S: String := "one"; S := "two";
But not this:
S: String := "one"; S := "three";
Or even this:
S: String := "three"; S := "one";
Nope, it's not maximum string length (like with SQL
varchar columns), it must literally be exactly the same length.
Fortunately while local variables are crazy like that, function arguments aren't so we're finally able to write a FizzBuzz:
with Ada.Text_IO; procedure FizzBuzz is function LStrip(S: String) return String is begin if S(S'First) = ' ' then return S(S'First+1 .. S'Last); else return S; end if; end LStrip; begin for I in 1..100 loop if I mod 3 = 0 and I mod 5 = 0 then Ada.Text_IO.Put_Line("FizzBuzz"); elsif I mod 3 = 0 then Ada.Text_IO.Put_Line("Fizz"); elsif I mod 5 = 0 then Ada.Text_IO.Put_Line("Buzz"); else Ada.Text_IO.Put_Line(LStrip(Integer'Image(I))); end if; end loop; end FizzBuzz;
I'll skip all the minor weirdness like
= for equality check,
() for substring, indexing starting from 1,
S'Last, and so on.
Should you use Ada?
Only if you're trying to sabotage Blue Origin. Otherwise, no.
If you're really exceedingly safety-obsessed, there's Rust for you.
Otherwise, just about any modern properly memory-managed language (so all except C and C++) with decent TDD will do just fine.
All code examples for the series will be in this repository.
Top comments (0)