Question

An Ada tutorial I'm reading says that this is a valid thing to do in Ada:

Large : array (0 .. 100) of Integer;
Small : array (0 .. 3) of Integer;

-- extract section from one array into another.
Small(0 .. 3) := Large(10 .. 13);

However, when I actually try it, it doesn't work.

I'm using ideone's online Ada environment to play with this stuff, for simplicity (link above). Is the tutorial wrong, or is it referring to a version of Ada which ideone doesn't implement?

Was it helpful?

Solution

The tutorial is wrong.

This will compile, though:

type Integer_Array is array (Natural range <>) of Integer;
Large : Integer_Array (0 .. 100);
Small : Integer_Array (0 .. 3);

...
Small (0 .. 3) := Large (10 .. 13);

The details: In my example, Integer_Array is a type (actually a type and a "first subtype"), and Integer_Array(0..100) and Integer_Array(0..3) are constrained subtypes. Array types in Ada specify the type(s) of the index(es) and the type of the element, but not the bounds; bounds are specified by subtypes, specifically constrained subtypes. (That doesn't mean that you need a subtype declaration; a type declaration can cause both a type and a constrained subtype to be defined.)

An Ada assignment requires (usually) that the source and destination be of the same type, but they can be different subtypes. So in my example, both the source and destination are subtypes of Integer_Array, and therefore the assignment meets this requirement.

In the original example, the declarations of Large and Small define new anonymous array types. Each type is unbounded, and the declarations also define bounded subtypes that are used as the variables' subtypes. But the important thing here is that two distinct types are defined, and you can't assign one type to the other. Furthermore, since the types are unnamed, you can't use a type conversion to make the assignment work, as you could in an example like this:

type Integer_Array is array (Natural range <>) of Integer;
Large : array (0 .. 100) of Integer;
Small : Integer_Array (0 .. 3);

...
Small (0 .. 3) := Integer_Array (Large (10 .. 13));

Here, Large and Small again have two distinct types, but a type conversion is possible because the destination type is named.

The moral here is that it's better to use named array types. Variable declarations like

Large : array (0 .. 100) of Integer;

can be good enough in some instances; but as this example shows, there are certain things you can't do with them.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top