Reasons for loving Ada. #1: strong typing
Tags: ada, strongtyping, correctness, debug
Published: 2017-12-10 16:41:32

---
title: Reasons for loving Ada. #1: strong typing
published: true
description: 
tags: ada,strongtyping,correctness,debug
---
Yes, yes, I know... I am kind of an oddball for programming in Ada.  When the matter comes out in conversations I am usually asked to defend this choice of mine.  For future reference (and maybe to help others knowing this nice language) I decided to write few articles about what I like in Ada. 

# History and other stuff

Before diving in the details, let me spend a couple of words about the language. Many never heard about Ada and many of those who did have some [prejudices about it](http://www.electronicdesign.com/dev-tools/11-myths-about-ada). 

The language Ada is named after [Ada Lovelace](https://en.wikipedia.org/wiki/Ada_Lovelace) daughter of [Lord Byron](https://en.wikipedia.org/wiki/Lord_Byron) (yes, _that_ Byron) and considered the [first programmer in history](https://en.wikipedia.org/wiki/Ada_Lovelace#First_computer_program).  

> Incidentally, did you notice that I write "Ada" and not "ADA"?  This is because it is a name of a person, not an acronym. Use "ADA" on an forum/newsgroup and you will be corrected in no time...

Ada was developed in the '80s following an idea of the Department of Defence. (I am not replicating here the interesting history that is available [elsewhere](http://www.adahome.com/History/).) Since then it was updated every approximately ten years giving rise to several releases, informally known with the year number (Ada 83, Ada 95, Ada 2005 and Ada 2012, next release will probably be Ada 2020). Ada is a language very alive and modern, with several feature not easily found elsewhere: contracts, type invariants, formal checking, private packages, distributed programming, native multitasking and so on...

> Ada is quite flexible: it is used to write million-line code in avionics, but also to control small devices like the  [STM32](http://blog.adacore.com/tag/STM32).  See, for example, this [segway implemented with a Lego mindstorm](https://www.youtube.com/watch?v=MWYHBxHTW54) controlled by a multitasking code (with a 16 bit processor and 64K of RAM!) [presented at FOSDEM](https://people.cs.kuleuven.be/~dirk.craeynest/ada-belgium/events/12/120204-fosdem/07-ada-segway-robot.pdf).

# Why do you love Ada?

A simple answer?  Reduced debugging time: my personal experience is that an Ada code will require maybe 1/10 of debugging time if compared with a C code of similar complexity. The reason is that  Ada compiler is much "stricter" than C, so that when the program compiles, it has an internal coherence that prevents the existence of many silly bugs (and most bugs are just silly!) that would have survived in a C code (functions with no return, a missing `break`/`case` in a `switch`, dangling pointers, buffer overflows...). The remaining bugs are easily caught by the many *bug traps* (I love this term) that the compiler adds to your code.  Programming in Ada is like doing [*pair programming*](https://en.wikipedia.org/wiki/Pair_programming), but with *the compiler* playing the role of the *observer*.

> Please note that *I am not* claiming that by using Ada your code will be *automagically* readable, maintainable and bug free.  You can write bad code in Ada, you just need to make an effort...  :-) 
> Seriously, it is often said that the quality of the code depends mainly from the skill of the programmer, rather than from the type of tools. Nevertheless, using the right tool will help you to achieve the same result with less effort. 

## OK, OK, I understand... But can you make me an example?

Sure, I am here for this.  Maybe the simplest characteristic of Ada that helps you in writing robust software is the *type system*, especially its *strong typing* nature. Let me explain with an example: if in C you write

```C
typedef int serial_number;
typedef int port;
```

you can assign with no problem a variable of type `port` to a variable of type `serial_port` since both are integers; but if you do in Ada

```Ada
type Serial_Number is new Integer;
type Port          is new Integer;
```
you _cannot_ assign a variable of type `Port` to a variable of type `Serial_Number` although both "under the hood" are implemented as integers.  This is because they actually *represents two different things* despite being implemented in the same way at the lowest level. Well, it makes sense, doesn't it? Why should you want to use a TCP port as a serial number?  Most probably, if you try to do such a thing, there is an error somewhere. 


> What if you actually need to use a port as a serial number?  No problem, you can convert it with `Serial := Serial_Number(Client_Port);`. Note that this conversion has no cost since both are integers; it is just a way to tell to the compiler "Listen, this is not an error, I know what I want, please bear with me and assign this value."

> Note the use of "camel case with underscores" for names that are not keywords.  This style is quite common in modern Ada code.  It is not mandatory, of course, but personally, I find it quite readable.  Please also note that Ada is case-insensitive, so that you could write, e.g., `serial_number`.  Oh, yes, and the use of ":=" for assignment.
 
Actually, the code above is not the best choice.  How do you know that an `Integer` will be large enough to keep a serial number or a port?  Well, on current Intel processor (whit 32-bit integers), that is quite reasonable, but what if you have a small micro-controller with 16 bit integers?  Well, maybe the best thing is to let the compiler to decide by writing

```Ada
type Serial_Number is range 0 .. 999_999;
type Port          is range 0 .. 2**16-1;
```

> Note the use of '_' as separator in numbers.  A simple thing, but really convenient...

Note how  we do *not* say to the compiler which low-level implementation to use, but which *characteristics* we need and let the compiler to decide how to handle them.  On a microcontroller with 16-bit `int`s maybe `Serial_Number` will be implemented as a `long int`, while `Port` will be an `unsigned int`. But who really cares? Let the compiler take care of this boring stuff...

> What if you need `Serial_Number` to have a specific size, say  24 bits (because, for example, you need to write it in a packet)?  Just write

```Ada
type Serial_Number is range 0 .. 999_999 with Size => 24;
```

> I do not want to dig deeper in the Ada type system, but I cannot resist telling you about two types that are not commonly found elsewhere.  If you write `type Volt is delta 0.125 range 0.0 .. 255.0;` the variables of type `Volt` will hold a [*fixed point real*](https://en.wikipedia.org/wiki/Fixed-point_arithmetic) ranging in the interval 0&nbsp;V..255&nbsp;V with step 0.125&nbsp;V. Fixed point numbers are usually implemented as integers and are used, for example, in some DSP applications running on small processors without floating point maths.  Another uncommon type is the *decimal fixed point* type defined with something like `type Money is delta 0.01 digits 15;`.  I'll let you [discover about them](https://en.wikipedia.org/wiki/Fixed-point_arithmetic#Binary_vs._decimal).  See also the corresponding [Reference Manual page](http://www.adaic.org/resources/add_content/standards/12rm/html/RM-3-5-9.html).

# An example: cleaning user input

Let us make a toy (but not so-toy) example of exploitation of the strict typing of Ada. 

> Someone could object that there are other ways to handle the problem considered here.  Yes, I know, but I just need a _simple_ example to show what you can do with strict typing.  I am not claiming that is the _only_ (or _best_) solution (although, I think it is quite good).

It is well known that in any application using user input care must be taken in using the user input since it could open security holes.  The following [xkcd comic](https://xkcd.com/327) is a classic

  
![alt text](https://imgs.xkcd.com/comics/exploits_of_a_mom.png "Exploit of a Mom")

Of course, we can pay all the attention we want to not use user input before sanitizing it, but if the application is very large and everything is a `String` (or `char*`), something can slip in the cracks...  Type strictness can help us here.  We just need to define a new type `Dirty_String` and have all the user input function return a `Dirty_String` rather than a string (this is easier to check).  The only way to transform a `Dirty_String` in a normal `String`  will be via a special `Sanitize` function.  

Let's dig into details.  We will define the following package _specs_

```Ada
package Dirty_Strings is 
  type Dirty_String(<>) is private;

  function Sanitize(X : Dirty_String) return String;

  function Taint(X : String) return Dirty_String;
private
  type Dirty_String is new String; 

  function Taint(X : String) return Dirty_String
  is (Dirty_String(X));
end Dirty_Strings;
```
> In Ada a package is divided into two parts: its _specs_ that specifies the "resources" exported by the package and its _body_ with the actual implementation.  The _specs_ are further divided into a _public_ part (visible to the rest of the code) and an optional _private_ part.

This package define a type `Dirty_String`.  In the *public* part (before the `private`) the type is defined as `private`, that is, *none of your business*.  Moreover, the package exports two function that can be used to convert from `Dirty_String` to normal `String` and vice-versa.

However, in the *private part* we see that a `Dirty_String` is just... a `String`. Putting its definition in the private part prevents *short-cut conversions* from `Dirty_String` to `String` and forces the programmer to go through the function `Sanitize` that, we guess, will do stuff like quoting special characters.  Instead, the conversion of a normal `String` to a `Dirty_String` is just a type conversion since there is no need to change it.  This allows us to define it as a *expression function* (see also the [RM](http://www.adaic.org/resources/add_content/standards/12rm/html/RM-6-8.html)) that, most probably, will be "inlined" by the compiler.

# Run-time constraints

Let me conclude with a feature of Ada 2012 that I find quit cute (and useful). Few years ago, I wrote a small package to write Matlab files from Ada.  One day I discovered that the package was writing files that could not be read from Matlab. The reason was that the names of the variables in the Matlab file were not valid Matlab names.  After correcting the bug, I decided to add a new _bug trap_ to the code. I defined the type to be used for variable names as

```Ada
type Matlab_Name is new
     String
   with Dynamic_Predicate =>
     (for all I in Matlab_Name'Range =>
        Is_Alphanumeric (Matlab_Name (I)) or Matlab_Name (I) = '_')
     and
       Is_Letter (Matlab_Name (Matlab_Name'First));
```

If you have a bit of programming experience, you should be able to understand the code above, even if you do not know Ada.  As you can see `Matlab_Name` is a `String` (but you cannot mix it with other strings, e.g., a filename!), but it also must satisfy a `Dynamic_Predicate` (a condition that is checked at run-time, if you ask the compiler to do so).  The condition can be split in two, the first part

```Ada
  (for all I in Matlab_Name'Range =>
        Is_Alphanumeric (Matlab_Name (I)) or Matlab_Name (I) = '_')
```

requires that every character in the name must be a letter, a digit or an underscore, while the second part

```Ada
Is_Letter (Matlab_Name (Matlab_Name'First));
```

requires that the first character must be a letter.  If checks are enabled and at some time your code generates a bad name, an exception will be raised precisely in the point were the bug happened. (This pinpointing of bugs helps a lot in debugging...)

> *What about efficiency*?  Yes, I can hear you, efficiency lovers.  The idea of having checks done at run-time seems to go against the idea of efficiency.  Well, it is true, run-time checks costs in term of efficiency, but in my experience you do not even notice it.  Unless you are on a very strict time budget (or unless you have very complex checks) it is usually more convenient to keep them on to catch possible bugs. You should take the decision of turning checks off only after discovering that you cannot afford them and you should turn off only those that are in most computationally intensive parts (possibly after thoroughly testing).

> An alternative approach is to code in [SPARK](https://en.wikipedia.org/wiki/SPARK_(programming_language)) (a subset of Ada, nothing to do with Apache) in order to check your code formally. I'll let you discover the joy of SPARK... :-)