6

In this question, I asked how to define an unlimited upper bound for a range (turns out that the answer was fairly obvious, but not to someone new to Ada). In the answer, it was suggested to create a Specific Subtype for this.

A specific subtype of of the sort referred to in the question would look like this:

Type Speed is Float range 0 .. Float'Last

Additionally, I've noticed that a good portion of the code in this Ada project has specific types - like Feet_Float and Meters_Float and the like. Why is this the preferred practice, as opposed to just putting a range constraint on a basic float member variable in the class/package?

theMayer
  • 15,456
  • 7
  • 58
  • 90

3 Answers3

8

Ada doesn't prefer subtypes - Ada programmers do.

New types and subtypes (they are different, and both have their uses) help catch so many errors at so little cost or time penalty it's a mystery why good type systems fell so far out of fashion.

For example, recognise that the index for any array belongs to a subtype (possibly anonymous, but accessible as myArray'range as in for i in myArray'range loop ... end loop; or subtype myIndextype is myArray'range; theIndex : myIndextype; and you'll see that every buffer overflow vulnerability - or attack - ever written was simply a type error - or could have been, in Ada.

When you get a bug past the compiler, the first time your executable falls over with an Exception : Constraint_Error pointing spookily close to the mistake, you'll start to get a sense of the value of range-constrained types.

To expand on this a bit, I'll refer to a couple more Q&As.

First note that the compiler you're probably using, Gnat, may not be strictly Ada compliant unless you add a couple of optional flags on the command line (or project file) as described in the first example. Recent versions have turned some of them on by default.

Here's an example of a subtype being declared, used and going out of visible scope, (in a declare block, where the range of the subtype is unknown until runtime. Unlike many dynamic typed languages, this is both fast and safe, because the relevant storage is usually on the stack, if you're interested in the implementation details.

And an example of how not to use a declare block.

Here's an extreme example of not only declaring subtypes but telling the compiler how to pack them in storage. Common in embedded programming, either where space is tight (I have a complete digital watch in a processor with 1kbyte memory!) or for accessing specific bits in hardware registers. (Note that this example would be cleaner if updated to use Ada-2012 aspects.)

And this Q&A briefly covers the difference between new types and subtypes, for someone coming from Java. (I'm a little disappointed none of the Java experts managed an answer before it was closed, describing how they would handle the same issues)

5

The declaration of specific types has the following benefits:

  • Specific types prevent inappropriate mixing of abstractions. For instance, dividing the distance between the Moon and Earth in meters by the gross national product of Belgium expressed in Euros.
  • The name of the type more clearly documents the intended use of the type
  • Use of ranged types clearly documents the valid values for instances of the type.
Jim Rogers
  • 4,822
  • 1
  • 11
  • 24
  • 1
    A good example is to prevent mixing pounds-seconds and neton-seconds which was the root cause of the Mars Climate Orbiter crash (https://en.wikipedia.org/wiki/Mars_Climate_Orbiter ) – Frédéric Praca Nov 23 '17 at 08:45
  • While that is indeed true, I suspect the use of specific subtypes in the context of MCO would not have been helpful. This was not so much a software programming issue, but rather a system interface verification issue - additionally, the systems engineering process broke down during the mission when the error should have been detected and corrected. – theMayer Nov 27 '17 at 14:42
5

The paradigm in Ada is to model the problem in the solution. One aspect of this is to model the range, accuracy, and precision of values in the problem space with appropriate scalar type and subtype definitions.

Why should one do this? McCormick, in analyzing why students with C experience and no Ada experience were able to complete his real-time S/W course's project in Ada but not in C found that the most important feature of Ada was

Modeling of scalar objects.

  • Strong typing.
  • Range constraints.
  • Enumeration types.

McCormick's paper

McCormick's site

Jeffrey R. Carter
  • 3,033
  • 9
  • 10
  • The OP mentionned `Feet_Float` and `Meters_Float`. Ada 2012 has a feature that might be of interest in addition to type/subtypes and constraints checks : dimensions. One may refer to this link https://www.adacore.com/gems/gem-136-how-tall-is-a-kilogram. Quote : `This feature relies on Ada 2012 aspect specifications, and is available from version 7.0.1 of GNAT onwards. The GNAT compiler now supports dimensionality checking.` This could also be an echo of other comments concerning Mars Climate Orbiter crash. – LoneWanderer Dec 12 '17 at 00:10