Accessing a constant array's elements by position

I have: my_array : constant array (1..3) of my_type := (2,5,12);

my_var1 := my_array’first; – gives 2
my_var2 := my_array’ ? ; – gives 5
my_var3 := my_array’last; – gives 12

Can I do this and if so, how do I capture the middle, second, value in the array that is 5?

My_Array (My_Array’First + 1)

You have the more “algebraically” correct way which is to use 'Succ on the 'First for the index :slight_smile:

1 Like

'Succ needs the type. In the declaration of a constant array the index type is anonymous types.

In another thread about reflection. With reflection there should be A’Index and A’Index (N), A’Element attributes returning the corresponding types.

For those who are in love with generics:

generic
type Vector is array (<>) of <>;
package …

That would be: … my_var2 :=my_array( ’first’succ); — ?

No.
The 'Succ attribute belongs to the type, not the value.

The issue with the as-presented code (my_array : constant array (1..3) of my_type := (2,5,12);) is that it is an anonymous array type, which means that you cannot reference the index-type. (Kinda.)

There are several ways that we can proceed, but first, a small reminder about Renames:

Example:
Declare
  Collection : Array(1..3) of Some_Type:= (Others => Generator);
  First  : Some_Type renames Collection(1);
  Second : Some_Type renames Collection(2);
  Third  : Some_Type renames Collection(3);
Begin
  -- Operations.
End Example;

This is actually a really good way to handle certain instances where you’re dealing with the elements in a more “individualistic” manner. (I’ve used this technique several times in Gnoga applications: an array of GUI-elements, and then using renames to give them meaningful names.)

Now, another option is to move the anonymous type into an actual type:

Type Vector is Array(Positive range <>) of Some_Type;
Collection : Constant Vector := ( 1..3 => Generator );

Now, this is using Ada’s unconstrained array idea: the Vector-type doesn’t have any bounds defined (i.e. unconstrained by its bounds). Also, see how the Collection takes its bounds from the initializing expression.

That allows the following:

Declare
  Collection : Vector:= (1..6 => Generator);
  One   : Some_Type renames Collection( Collection'First ); -- Index by the first index,
  Two   : Some_Type renames Collection( Positive'Succ(Collection'First) ); -- by the next,
  Three : Some_Type renames Collection( Collection'Last ); -- and the last index.
Begin
  -- Operations.
End Example;

Why do you both say this? When you use numeric literals to define the bounds, the index subtype is an anonymous subtype of Integer, but you can still use Integer’Succ and the like.

with Ada.Text_IO;

procedure Anon_Type is
   C : constant array (1 .. 3) of Integer := (2, 5, 12);
begin -- Anon_Type
   Ada.Text_IO.Put_Line (Item => Integer'Image (C'First) &
                                 Integer'Image (Integer'Succ (C'First) ) &
                                 Integer'Image (C'Last) );
end Anon_Type;

compiles fine and outputs

 1 2 3

as expected.

1 Like

my_var1 = 1
my_var3= 3

my_array’first refers to the first index of my_array. Not its value at that position
my_array’first refers t the last index of my_array. Not its value at that position

my_array(my_array’first) refers to the first element

/Björn

Because, as defined, the type of the object is anonymous.
This, and constrained/unconstrained arrays, are very important concepts that a newcomer should know.
IIRC, your example works because the index is regarded to be Standard.Integer… though I’m not at all certain, and it could be a bug in GNAT allowing non-Standard.Integer values to use/interoperate with Integer'Succ( X ).

Thanks. Ada is so cool, and so many nuances..

Yes, the array type is anonymous, but you seemed to be saying that the index type is anonymous. ARM 3.6(18) defines the index type to be Integer.

What makes you think I was using GNAT? In fact, my example works with both GNAT and ObjectAda.

Thanks all who helped with my little array element by position question. Just curious on a related subject that came up. I am using GNATStudio myself for managing my Ada things and it calls the gcc-13… compiler for compile link and build. What role does GNAT have other than calling gcc-13.xx’s /bin gprbuild.. etc?

Do you mean GNAT or GNATStudio? GNAT’s role is the front end Ada compiler that is part of GCC. GNATStudio is just an IDE tailored to work with GNAT, GPRBuild, and [now] Alire

Sorry if that doesn’t answer your question. I wasn’t sure exactly, so my apologies.

I did mean GNATStudio as I wrote, but I see now the statement I was referring to was about GNAT. So bug in my question.But I didn’t think GNAT was part of the GCC-14… compiler, link, build, but the reverse that GNAT and or GNATstudio gathered the parameters to pass with its call to the gcc compiler.