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.
Hello, World!
Let's start with hello_world.adb
:
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.
Fibonacci
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
to"7"
. In some weird idea of consistently since-7
converts to-7
, 7 converts to7
with 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'Image
syntax for function in a package looks really weird, especially since we also have more familiar.
on the same line.
FizzBuzz
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'First
and 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.
Code
All code examples for the series will be in this repository.
Top comments (0)