Ada Programming/Libraries/Ada.Containers.Vectors

is a unit of the Predefined Language Environment since Ada 2005.

This generic package supplies a container (Vector) which can store any definite subtype in a consecutive list. This makes an .Vector similar to an array &mdash; however a Vector can change size after it has been declared, which an array can't do. For that reason, vectors are also known as dynamic arrays or resizable arrays.

Introduction
One of the major additions to Ada 2005 is the container library. This library enables the Ada developer to manipulate data structures such as doubly linked lists, maps, sets and vectors. This page will show how the Ada.Containers.Vectors package works.

But first: What is a vector? Here's what the reference manual has to say about it:

"The language-defined generic package Containers.Vectors provides private types Vector and Cursor, and a set of operations for each type. A vector container allows insertion and deletion at any position, but it is specifically optimized for insertion and deletion at the high end (the end with the higher index) of the container. A vector container also provides random access to its elements.

A vector container behaves conceptually as an array that expands as necessary as items are inserted. The length of a vector is the number of elements that the vector contains. The capacity of a vector is the maximum number of elements that can be inserted into the vector prior to it being automatically expanded.

Elements in a vector container can be referred to by an index value of a generic formal type. The first element of a vector always has its index value equal to the lower bound of the formal type.

A vector container may contain empty elements. Empty elements do not have a specified value."

Basically it's a one-dimensional array, and in many ways it behaves just like an array, allowing both random and sequential access to the elements of the vector. The main difference, is that a regular array is bound in size, whereas a vector is not, insofar as there are enough resources available to contain the vector. A vector will expand automatically when new elements are added.

The flexibility of vectors is a wonderful thing, but it does come at a cost: A vector is not as fast and lightweight as a regular array. Vectors are by no means slow and/or resource-hungry, but they are both slower and heavier than a regular array. On the other hand, if you can live with the higher resource demands, vectors do give you a great set of very intuitive tools to manage your lists of data.

Using Ada.Containers.Vectors
Learning how to use the library is, in my humble opinion, best done with actual, working code. I'm not a big fan of pseudo-code, so all examples on this page will compile and work.

The examples all center around a small "Quotes by Linus Torvalds" application, where we have a bunch of quotes in a regular, flat text file. The file will be used throughout all the examples, and it looks like this:

I have an ego the size of a small planet. My name is Linus Torvalds and I am your god. Do you pine for the days when men were men and wrote their own device drivers? If you need more than 3 levels of indentation, you're screwed anyway, and should fix your program. You know you're brilliant, but maybe you'd like to understand what you did 2 weeks from now. An infinite number of monkeys typing into GNU emacs would never make a good program. Is "I hope you all die a painful death" too strong? Most days I wake up thinking I'm the luckiest bastard alive. I'm always right. This time I'm just even more right than usual. And what's the internet without the rick-roll?

In case it isn't obviously clear, each line represents one quote from Linus.

The idea is that quotes are added and removed from this file on a whim, and as such the program doesn't know how many quotes there are before we've read them all, making vectors the perfect data structure to both hold and manipulate all the quotes.

We're not actually going to build the entire application. We'll just focus on the part where the quotes are read from the  file, and then added to a vector.

Before we start on the actual code, lets take a peek at the beginning of the  specification:

Note the types  and. The former is what defines the index of the vector and the latter is the type of elements the vector contains. With that in mind, lets have a look at the basic  program itself:

If we focus on the vector related parts of the program, we see that on line 4 the library unit is added to the program. This step is vital to being able to use the vectors at all, just as  is necessary for basic string IO. If this concept is unfamiliar to you, you should probably read up on the basics of Ada and then return here again.

With the vectors library readily available, we turn our attention to line 9, where we instantiate the  generic with the parameters   and. The result is a vector where the index starts at 0 (remember that  is a subtype of   with the range  ) and the elements are of type. On line 11 we declare the  variable as type. We don't need the full declaration,, because of the   clause at line 10.

We now have a working vector,, so the next natural step is adding some data to it. This is done on line 18, where each quote is appended to the vector, using the  procedure. Finally we close the file, and exit the program.

This little  program is the foundation on which this entire article is built. Nearly all of the examples below are simply expanding on this program. But before we move ahead with the various procedures and functions of the vectors library, lets take short look at the vectors package for indefinite types.

Ada.Containers.Indefinite_Vectors
The sibling library is available for indefinite types. It works in much the same way as, except for a few omitted   procedures. Here's an example on how it works:

Compile and execute this code, and you get:

No. of quotes: 10 Quote no. 2: My name is Linus Torvalds and I am your god.

It is important to note, that the indefinite vectors are slower than the constrained vectors, so avoid them if performance is important.

Because the definite and indefinite containers are so alike, the rest of this article will concern itself only with the definite version of the vectors library.

Procedures and functions
There's a lot of procedures and functions in the  package. Luckily they are all very aptly named, so figuring which procedure or function you need for a specific situation is usually pretty simple. To further help in identifying what exactly procedure X or function Y does, I've divided them into several groups, according to their main functionality.

Some procedures/functions might fit in more than one category. In those cases, I've placed them in the category in which I feel they are the most commonly used.

Setting a vectors size/capacity
In the  package there are tools available to create vectors of a specified size/capacity. The primary goal of these methods is to enable the programmer to assign the amount of resources needed, thereby getting rid of the performance overhead of calling Reserve_Capacity internally whenever a new element is added to the vector.

Vectors.Reserve_Capacity
Here's the specification for :

The Ada Reference Manual explains  best:

"Reserve_Capacity allocates new internal data structures such that the length of the resulting vector can become at least the value Capacity without requiring an additional call to Reserve_Capacity, and is large enough to hold the current length of Container. Reserve_Capacity then copies the elements into the new data structures and deallocates the old data structures. Any exception raised during allocation is propagated and Container is not modified."

There are really only a few cases where using  makes any sense, and some of those rare cases are:


 * Prepare resources for a vector of a certain size
 * Release excessive resources

Of course there might be several other reasons, but those two are probably the most common, with the first one being the absolute winner. So, lets go ahead and add the following code to the body of the  program, after the call to   on line 20:

Compile and execute  and you get:

Capacity: 16 Capacity: 100

Lets try and expand a bit on the  program, and see how we can manipulate the vector during execution of the program. Place this before the call to :

And this after the call to :

And the output:

Capacity: 100 Length: 0 Capacity: 100 Length: 10 Capacity: 10 Length: 10

If you're working with big vectors, it might be worth it to check if a few well-placed  calls can speed up your code and/or save you some resources, but as with all optimization: Don't do it prematurely and test it rigorously.

Vectors.Set_Length
Here's the specification for :

One might wonder what the point of a procedure like  is, since the vector will just grow as new elements are appended/prepended/inserted, so why? In order to answer this question, it's important to understand that a vector's length can never exceed its capacity.

The capacity of a vector is the number of internal data structures set aside for the vector. This might be a lot higher than the vector's actual length, but it can never be less (see Vectors.Capacity). So when a new element is added to a vector, first the capacity of the vector is expanded using Reserve_Capacity (if necessary of course) and then the new element is added. So adding 100 new elements to a vector, effectively calls Reserve_Capacity 100 times. Surely this is a waste of resources, and it's exactly that waste we can avoid by using. If we know we'll be adding a bunch of new elements, we can accumulate all those calls to Reserve_Capacity into one call to. This is much more efficient.

Another use for  is to shorten a vector, as we'll see in the following example:

And the output:

Length of vector: 10 Length of vector: 20 Length of vector: 5

To show the benefits of using, I've done two small programs. The first adds 10_000_000 new elements using. The second program does the same, but it does so using  and.

Here's how this looks when timed on my computer:

Length: 0 Length: 10000000 real   0m0.438s user   0m0.336s sys    0m0.096s

Now, let us rewrite this little gem with the aid of  and re-time it:

And here are the numbers for this version:

Length: 0 Length: 10000000 real   0m0.109s user   0m0.064s sys    0m0.044s

This is a massive improvement in execution time, so be sure to use  if you need to add lots of new elements to a vector.

The above results are an average of 10 runs.

Vectors.To_Vector
The specification for  looks like this:

It should be very obvious what the two  functions do. I'm going to lump the examples for both functions together, as they are so alike. Add this to the body of the  program:

And the output is:

1st. element: I have an ego the size of a small planet. 10th. element: And what's the internet without the rick-roll? 1st. element: 10th. element: 1st. element: Put new quote here 10th. element: Put new quote here

So what have we learned? Well, the first  function creates a new vector with   empty elements, and the second   functions creates a new vector with   elements that all have the value.

As we'll learn later, it is actually a bounded error to read an empty element, so the second   is probably the safest to use, as you force a valid value into each element.

Inserting data and/or empty elements
Inserting data into a vector is a crucial part of working with vectors. Empty vectors are usually not that interesting, so lets see how we can add some data to them.

Vectors.Append
The specification for  looks like this:

What  does, is add elements or other vectors to the end of a vector.

If we add some output functionality to the program, we can see how this works:

The  function will be discussed in detail later, but for now it's enough to know that the   function returns the element  found at the given index, in this case index 10.

Executing the program should result in the following output:

And what's the internet without the rick-roll?

To make it absolutely clear what  does, lets add these three lines to the body of the program:

Executing the program, we now get this output:

And what's the internet without the rick-roll? Test append

Looking at the specification for the first  procedure, you might've noticed the optional   parameter. The functionality of this parameter closely matches its name, as it enables you to repeat the insertion of the element  amount of times. Lets see it in action. Try adding this to the body of the  program:

And the output:

And what's the internet without the rick-roll? Test append Test append Test append

In the above example, we've used a  value of three, and as expected the element "Test append" is appended to the vector three times.

The second  procedure in the   package appends a vector to another vector. To see how this works, we'll need to create a new vector, which requires an addition to the declarative part of the program. Add the following declaration:

What we've just done is declare a new vector,. This is the vector we will append to the  vector.

Now add this to the body of the program:

The output of executing this program is:

And what's the internet without the rick-roll? My 1st. quote My 3rd. quote

Notice that we're using the same method as if we had appended a regular element, except that there's no  parameter used in the   procedure that appends vectors.

There's not much else to say about the  procedure, so lets move on to its sibling:.

Vectors.Prepend
The specification for  looks like this:

is very similar to, the only difference being that data is inserted at the beginning of the vector instead of at the end. To see it in action, add the following to the body of the basic  program:

The result when running the program is, as expected:

I have an ego the size of a small planet. Prepended! I have an ego the size of a small planet.

As you can see, the "Prepended!" text is added to the vector before the ego quote from Linus.

It is also possible with  to join two vectors. The functionality is the same, the only difference being that a vector is being copied instead of a single element.

Vectors.Insert
The specification for  looks like this:

enables us to insert one or more identical elements anywhere in the list. It also introduces us to a new concept: Cursors.

But lets start with the  procedures that are using the index to identify individual elements. Since they are very similar to each other, I'll put them all in the same example. Add the following to the body of the  program:

The output of this program is:

0 I have an ego the size of a small planet. 1 New second index! 2 My name is Linus Torvalds and I am your god. 3 Do you pine for the days when men were men and wrote their own device drivers? 4 Two new elements @ 4 and 5! 5 Two new elements @ 4 and 5! 6 If you need more than 3 levels of indentation, you're screwed anyway, and should fix your program. 7 You know you're brilliant, but maybe you'd like to understand what you did 2 weeks from now. 8 An infinite number of monkeys typing into GNU emacs would never make a good program. 9 Is "I hope you all die a painful death" too strong? 10 Most days I wake up thinking I'm the luckiest bastard alive. 11 I'm always right. This time I'm just even more right than usual. 12  13   14 And what's the internet without the rick-roll?

Note that the last call of  does not insert two empty elements. Instead, two elements of the vectors default value is inserted. As far as I know, this value currently is empty, but I wouldn't rely on it. If you need to insert empty elements, look further down for the  procedures.

With  you can insert new elements anywhere in the vector, simply by setting the   parameters appropriately. The vector will expand as necessary and elements following the  index will be pushed down by the amount of the   parameter (the default for which is 1).

The remaining  procedures all make use of a cursor. With a cursor you address both the vector and the element. In the next example I'll show all the  procedures using cursors. In order to use a cursor, we must first declare it, so add the following to the  declaration:

And add the following to the body:

The result of running the program is:

0New index 0! 1I have an ego the size of a small planet. 2My name is Linus Torvalds and I am your god. 3Do you pine for the days when men were men and wrote their own device drivers? 4New index 4! 5New index 5 and 6! 6New index 5 and 6! 7If you need more than 3 levels of indentation, you're screwed anyway, and should fix your program. 8You know you're brilliant, but maybe you'd like to understand what you did 2 weeks from now. 9New index 9 and 10! 10New index 9 and 10! 11An infinite number of monkeys typing into GNU emacs would never make a good program. 12Is "I hope you all die a painful death" too strong? 13Most days I wake up thinking I'm the luckiest bastard alive. 14I'm always right. This time I'm just even more right than usual. 15 16  17And what's the internet without the rick-roll?

When I first wrote this, I had a hard time coming up with good reasons for using cursors with the library - To me, using the index seemed more natural and more "in tune" with a vector, but later on I learned that there are in fact at least two good reasons for having cursors available:


 * They make generic algorithms possible
 * If a program is created using cursors, it is easy to switch to one of the other sequence containers

So there are in fact at least two good reasons for using cursors. Of course, if you are computing index values, using cursors doesn't gain you anything. As usual we have to think hard about what we need, and choose the tools accordingly.

Vectors.Insert_Space
When you need to insert a bunch of "empty" elements, then  is just the right tool for the job. The specification for  looks like this:

An important thing to note when working with, is that "empty" elements really don't mean that. Here's what the Reference Manual has to say about it:

"Then Insert_Space slides the elements in the range Before .. Last_Index (Container) up by Count positions, and then inserts empty elements in the positions starting at Before."

And later:

"Reading the value of an empty element by calling Element, Query_Element, Update_Element, Swap, Is_Sorted, Sort, Merge, " = ", Find, or Reverse_Find is a bounded error. The implementation may treat the element as having any normal value (see 13.9.1) of the element type, or raise Constraint_Error or Program_Error before modifying the vector."

The important thing to take away from all this, is that "empty" really means "unpredictable value". It all depends on the compiler, and how it treats the new element, so don't expect  to deliver neat and tidy empty elements. It may well just hand you a bunch of copies of already existing elements or some other value, as long as it is valid in the context of the Vector, in our case meaning an. Also please note that some compilers may raise  or   if you try to use an   function on the "empty" element. In the case of GNATMAKE GPL 2008 (20080521), which is what I'm currently using, the empty elements are treated as having any normal value of the element type.

With that out of the way, lets move on and see how  behaves in actual code. First add this to the declarative part of the  program:

Now we can also use the cursor edition of. Next we add this to the body of the program:

And here's the resulting output:

0 I have an ego the size of a small planet. 1 My name is Linus Torvalds and I am your god. 2 Do you pine for the days when men were men and wrote their own device drivers? 3 If you need more than 3 levels of indentation, you're screwed anyway, and should fix your program. 4 You know you're brilliant, but maybe you'd like to understand what you did 2 weeks from now. 5 An infinite number of monkeys typing into GNU emacs would never make a good program. 6 Is "I hope you all die a painful death" too strong? 7 Most days I wake up thinking I'm the luckiest bastard alive. 8 I'm always right. This time I'm just even more right than usual. 9 And what's the internet without the rick-roll?

0 I have an ego the size of a small planet. 1 My name is Linus Torvalds and I am your god. 2 I have an ego the size of a small planet. 3 My name is Linus Torvalds and I am your god. 4 Do you pine for the days when men were men and wrote their own device drivers? 5 If you need more than 3 levels of indentation, you're screwed anyway, and should fix your program. 6 You know you're brilliant, but maybe you'd like to understand what you did 2 weeks from now. 7 An infinite number of monkeys typing into GNU emacs would never make a good program. 8 If you need more than 3 levels of indentation, you're screwed anyway, and should fix your program. 9 You know you're brilliant, but maybe you'd like to understand what you did 2 weeks from now. 10 An infinite number of monkeys typing into GNU emacs would never make a good program. 11 Is "I hope you all die a painful death" too strong? 12 Most days I wake up thinking I'm the luckiest bastard alive. 13 I'm always right. This time I'm just even more right than usual. 14 15 16 17 And what's the internet without the rick-roll?

The first thing we notice, is that the vector is 18 positions long after the various calls to. This matches perfectly with the three  parameters: 2 + 3 + 3 = 8 plus the original length of 10. Then we notice that in some places  has inserted what appear to be empty elements (positions 14-16), whereas in other places, copies of already existing elements have been inserted (positions 0-1 and 8-9). This shows the "unpredictable value" behavior I mentioned at the beginning.

So when you're using, don't think of it as a procedure that does exactly what its name would seem to imply. Think of it as a procedure that simply expands the length of the vector at a specified index. In other words:  should primarily be used to quickly expand the vector with   elements at the   position and you should never rely on those elements having any real meaning until you've filled them with some valid data. Thus the access we're doing above in the final loop is not a very bright thing to do. We could've experienced a raised exception due to the call to, as noted in the reference manual quote.

We can avoid this "issue" by using the Replace_Element procedure to fill the empty elements with some real data:

And the output is:

0 I have an ego the size of a small planet. 1 My name is Linus Torvalds and I am your god. 2 Do you pine for the days when men were men and wrote their own device drivers? 3 If you need more than 3 levels of indentation, you're screwed anyway, and should fix your program. 4 You know you're brilliant, but maybe you'd like to understand what you did 2 weeks from now. 5 An infinite number of monkeys typing into GNU emacs would never make a good program. 6 Is "I hope you all die a painful death" too strong? 7 Most days I wake up thinking I'm the luckiest bastard alive. 8 I'm always right. This time I'm just even more right than usual. 9 And what's the internet without the rick-roll?

0 New index 0 1 New index 1 2 I have an ego the size of a small planet. 3 My name is Linus Torvalds and I am your god. 4 Do you pine for the days when men were men and wrote their own device drivers? 5 New index 5 6 New index 6 7 New index 7 8 If you need more than 3 levels of indentation, you're screwed anyway, and should fix your program. 9 You know you're brilliant, but maybe you'd like to understand what you did 2 weeks from now. 10 An infinite number of monkeys typing into GNU emacs would never make a good program. 11 Is "I hope you all die a painful death" too strong? 12 Most days I wake up thinking I'm the luckiest bastard alive. 13 I'm always right. This time I'm just even more right than usual. 14 New index 14 15 New index 15 16 New index 16 17 And what's the internet without the rick-roll?

With those Replace_Element calls in place, we can safely read the entire vector in the final loop, using the   function, without having to worry about raising any exceptions.

Reading and querying the vector
Just as important as adding data to a vector, is being able to read the data, so lets have a look at some of the methods available to do just that.

Vectors.Element
We've already met the  function while going over the previous procedures and functions, so what it does and how it works should be apparent by now. That won't stop us, however, from giving it the once-over just like the rest of the Vectors package. Here's the specification for the two  functions:

We have one  function where we access the elements using an index, and one where we're using a cursor. Both do the same thing: Return the  on the given location in the vector. Here's an example using the index:

And the output of this is:

I have an ego the size of a small planet. Most days I wake up thinking I'm the luckiest bastard alive.

The cursor example requires an addition to the declarative part of the  program:

After that we add this to the body of the  program:

And the output is:

I have an ego the size of a small planet. Most days I wake up thinking I'm the luckiest bastard alive.

is quite straightforward. Whether you use an index or a cursor is a matter of taste. It seems worth noting that most of the cursor related procedures and functions in the Vectors package internally translate the cursor to an index and then use the index procedure/functions to do the actual heavy lifting. Due to this, I usually avoid the cursor forms. I think an index is much easier to work with and relate to. The primary benefit of using the cursor forms is one of flexibility. If you use cursors, your code will work, with very few changes, with the other sequence based containers, such as doubly linked lists.

Vectors.Query_Element
Here's the specification for :

is both similar to and different from the  function. Where  returns the   on the given index,   hands the   over to the   parameter. This parameter accepts a procedure that handles the. To show how this work, we'll first need to add a new procedure to the specification of the  program:

All we do in this procedure is output the element and concatenate 42 to the output.

Also in order to use a cursor, we must declare it first:

The next bit of code should be added to the body of the  program. We'll lump both the index and the cursor versions of  into the same example:

Note the  attribute. This returns a pointer to the  subprogram, and it is absolutely required for the   parameter. It is not enough to just write, as you can also see from the specification, where it says.

The output from this program is:

I have an ego the size of a small planet. 42 Most days I wake up thinking I'm the luckiest bastard alive. 42

Whether to use  or   is a matter of performance vs. clutter. is faster than, but the mess of using a call-back procedure is, perhaps, not worth the cluttering of the source code, unless performance is crucial. The larger the elements are, the more performance will suffer when using.

Alteration - how to "poke" the elements
Changing the data in a vector is a common task. Here are two methods to accomplish this.

Vectors.Update_Element
If you need to update elements in a vector, the  procedures will come in handy. They work in much the same way as, i.e. you must create a callback procedure to handle whatever it is you're trying to do to the elements in the vector. Here's the specification for :

Notice how these two procedures look almost exactly like the  procedures. The most crucial difference is the  parameter, where the parameter mode is now , as opposed to   for the   procedures. Because they are so alike we'll declare the same cursor and the callback procedure from the   example. We will only change the parameter mode:

And just as with, I'll show both the index and the cursor example in the same listing:

The output from this program is:

I have an ego the size of a small planet. 42 Most days I wake up thinking I'm the luckiest bastard alive. 42

is not the only way to alter the contents of an element in a vector. There are other ways to concatenate "42" to our Linus quotes, and one of those methods is, which we will look at next.

Vectors.Replace_Element
Where the previously discussed  procedure updates an element in situ,   assigns a new   to a given index or position, regardless of the content already there. Here's the specification for :

Using  is very similar to the   procedures, except you're now working on an index that already contains a value instead of creating a new index. Leave the  declaration from   and add the following to the body of the   program:

And the output from this program is:

I have an ego the size of a small planet. New index 0 Most days I wake up thinking I'm the luckiest bastard alive. New index 7

When to use  and when to use   is highly dependent on what it is you're trying to accomplish. Just remember that  updates the element on the given index in situ, whereas   completely replaces the element on the given index, and just as with   and ,   is faster than  , but it clutters the source code with a call-back procedure. So as with so many other things, it's a trade-off between clean code and performance, so be sure to test things and choose the best fit for the project.

Deleting and clearing
It is, of course, possible to delete elements from a vector and clear a vector completely. I bet the attentive reader will already gave guessed the names of these procedures. There are some surprises, however.

Vectors.Clear
Here's the specification for :

removes all the elements from a vector, but does not change the capacity of the vector. So if you want to reset a vector, while retaining the vectors capacity, then  is the way to go. Try adding this to the body of the  program:

And the output is:

Capacity before clear: 16 No. of quotes before clear: 10 Capacity after clear: 16 No. of quotes after clear: 0

Note that your capacity numbers might differ from the above. The important thing to note is that the capacity is the same, before and after calling. What is changed is the length value for the contents of the vector.

Unfortunately therefore, you cannot trust  to actually delete data from the vector. What this means is that if you resize the now "empty" vector you will probably find your data again. To see how that works, add this to the program:

The output is not as expected, certainly not as desired:

Capacity before clear: 16 No. of quotes before clear: 10 Capacity after clear: 16 No. of quotes after clear: 0 I have an ego the size of a small planet.

Vectors.Delete
Here's the specification for :

These two procedures delete elements from the vector. As you can see, there's a version using an index and one using a cursor. I'll show both in the same example, as they are very similar in use.

The  parameter tells   how many elements to remove from the vector. If there are fewer elements than, all the elements are removed from the vector. If you try to delete an index that does not exist, a  exception is raised.

We need a cursor for the  example, so add this to the declarative part of the   program:

And here's the body code for the  example:

And this is the output generated by the above:

0 I have an ego the size of a small planet. 1 If you need more than 3 levels of indentation, you're screwed anyway, and should fix your program. 2 You know you're brilliant, but maybe you'd like to understand what you did 2 weeks from now. 3 An infinite number of monkeys typing into GNU emacs would never make a good program. 4 And what's the internet without the rick-roll?

If the  parameter is 0, then nothing is done.

Vectors.Delete_First
Here's the specification for :

It should be quite obvious what the  procedure does. It deletes the first  elements from the vector. To see an example, add this to the body of the  program::

The output from the above program is:

No. of quotes: 10 I have an ego the size of a small planet. No. of quotes: 9 My name is Linus Torvalds and I am your god. No. of quotes: 4 Is "I hope you all die a painful death" too strong?

completely removes the element(s) from the vector - it doesn't just delete the contents and leave you with one or more empty elements. If you try to delete more elements than the vector contains, a  is raised, after the entire vector has been deleted. If  is 0, then   does nothing.

Vectors.Delete_Last
Here's the specification for :

The observant reader will notice that this procedure is very similar to the above mentioned  procedure and because they are so similar, the following will be an almost letter-by-letter copy of the   text.

The  procedure does deletes the last   elements from the vector. To see an example, add this to the body of the  program::

The output from the above program is:

No. of quotes: 10 And what's the internet without the rick-roll? No. of quotes: 9 I'm always right. This time I'm just even more right than usual. No. of quotes: 4 If you need more than 3 levels of indentation, you're screwed anyway, and should fix your program.

completely removed the element(s) from the vector. It also doesn't just delete the contents and leave you with one or more empty elements and the constraints on  are the same as for.

Moving, swapping and reversing
Sometimes it is necessary to move an entire vector to a new vector, to swap values in a vector or perhaps reorder the vector in reverse direction. The following methods will help with that.

Vectors.Move
Here's the specification for :

Moving data from one vector to another can be done using the  procedure. Add this to the declarative part of the  program:

And this to the body:

The output is:

Quotes length: 10 My_Quotes length: 0 Quotes new length: 0 My_Quotes new length: 10

Vectors.Reverse_Elements
Here's the specification for :

The  procedure is yet another one of those procedures that does exactly what its name says: It reorders the elements in the vector in reverse order. Lets try it:

And the output is:

I have an ego the size of a small planet. And what's the internet without the rick-roll?

And that's more or less all there is to say about.

Vectors.Swap
Here's the specification for :

The two  procedures exchange the values at positions   and   with each other, meaning the value at position   is moved to position   and vice versa. It's the same functionality for both the  procedure and for the   procedure, so I'll show both in the same example. First we must add two new variables to the declarative part of the  program:

And the add this to the body:

The output from this program is:

I have an ego the size of a small planet. And what's the internet without the rick-roll? And what's the internet without the rick-roll? I have an ego the size of a small planet.

Note that a  is raised if one of the indexes that is being swapped is out of range.

Using, it is very easy to add a  Bubble Sort to the   program. Please note that I'm just using a Bubble Sort as an example - you should never use something like this to sort your data, as it is very slow and inefficient.

Information about a vector
A fair deal of information about a given vector can be obtained using the following methods.

Vectors.Capacity
returns the current capacity of a vector. It's important to understand, that the capacity is not the same as the size of the vector; instead you should think of it as the size to which a vector can grow before new data structures must be allocated to the vector.

Here's the specification for :

Lets see how it works. Add this to the body of the  program:

And the output:

Capacity: 16 Capacity: 16

The capacity of the  vector is 16, even though we know there are only 10 quotes in it. Even if we clear the  vector, the capacity stays at 16. Lets expand a bit on the  program to see how the vectors package handles capacity. I'll post the full source here:

And the output:

Capacity (pre loop): 0 Length (pre loop): 0 Capacity: 1 Length: 1 Capacity: 2 Length: 2 Capacity: 4 Length: 3 Capacity: 4 Length: 4 Capacity: 8 Length: 5 Capacity: 8 Length: 6 Capacity: 8 Length: 7 Capacity: 8 Length: 8 Capacity: 16 Length: 9 Capacity: 16 Length: 10 Capacity (post loop): 16 Length (post loop): 10

Notice how length and capacity don't necessarily match. The capacity of a vector will always be the same or higher than the length. Capacity seems to expand as a power of 2 when we leave it to the system to adjust it, while the length is a linear count of the data actually added.

Vectors.Is_Empty
The specification for  looks like this:

With the  function we can test if a vector is empty or not. Add this to the  body, to see how it works:

And the output:

Not empty! Empty!

Note that empty in this context means a vector with no elements, not a vector with a bunch of empty elements. What the  function checks for is the length of the vector. If it's > 0, then  returns FALSE and if the length equals 0, then   returns TRUE.

Vectors.Length
Here's the specification for :

We've already encountered the  function in previous examples, but in case you didn't pay any attention to them, here's the short explanation of what   does: It returns the length (i.e., the count of elements) of a vector. I bet that was a surprise!

Lets see an example. Add this to the body of the  program:

And the output:

10 0

And that concludes our look at.

Iterating the vector
Iterating a vector can be done using simple loops, but why not use the built-in methods instead? These are not as flexible as a customized loop, but if a simple "array-walk" is all we need, then these methods are the way to go.

Vectors.Iterate
As easy as it is to iterate a vector using either the index or a cursor, there's an even simpler way: The  procedure.

Here's the specification for :

enables you to apply the  procedure to each element in the vector. As with the  and   procedures, we must create a procedure to handle the individual elements. For this example we'll go for a small procedure that reverses each quote and then outputs the resulting gibberish to the screen. Add this to the declarative part of the  program:

And next add this to the body:

The output from this program is:

.tenalp llams a fo ezis eht oge na evah I .dog ruoy ma I dna sdlavroT suniL si eman yM  ?srevird ecived nwo rieht etorw dna nem erew nem nehw syad eht rof enip uoy oD  .margorp ruoy xif dluohs dna ,yawyna dewercs er'uoy ,noitatnedni fo slevel 3 naht erom deen uoy fI  .won morf skeew 2 did uoy tahw dnatsrednu ot ekil d'uoy ebyam tub ,tnaillirb er'uoy wonk uoY .margorp doog a ekam reven dluow scame UNG otni gnipyt syeknom fo rebmun etinifni nA ?gnorts oot "htaed lufniap a eid lla uoy epoh I" sI  .evila dratsab tseikcul eht m'I gnikniht pu ekaw I syad tsoM .lausu naht thgir erom neve tsuj m'I emit sihT .thgir syawla m'I ?llor-kcir eht tuohtiw tenretni eht s'tahw dnA

Very elegant. Using  for simple manipulations of the elements in a vector is exactly what it's made for. For very complex things it might not be the best solution, as you can't pass any parameter to the  procedure, which naturally limits it somewhat in use.

Vectors.Reverse_Iterate
Here's the specification for :

Where  works its way through the vector from first to last,   does the opposite. Other than that little difference, the two procedures are exactly the same, so the example I'm going to show on how to use  is almost the same as the example for.

First we add the  procedure to the declarative part of the   program:

And the output is, as expected:

9 ?llor-kcir eht tuohtiw tenretni eht s'tahw dnA 8 .lausu naht thgir erom neve tsuj m'I emit sihT .thgir syawla m'I 7 .evila dratsab tseikcul eht m'I gnikniht pu ekaw I syad tsoM 6 ?gnorts oot "htaed lufniap a eid lla uoy epoh I" sI 5 .margorp doog a ekam reven dluow scame UNG otni gnipyt syeknom fo rebmun etinifni nA  4 .won morf skeew 2 did uoy tahw dnatsrednu ot ekil d'uoy ebyam tub ,tnaillirb er'uoy wonk uoY 3 .margorp ruoy xif dluohs dna ,yawyna dewercs er'uoy ,noitatnedni fo slevel 3 naht erom deen uoy fI 2 ?srevird ecived nwo rieht etorw dna nem erew nem nehw syad eht rof enip uoy oD  1 .dog ruoy ma I dna sdlavroT suniL si eman yM  0 .tenalp llams a fo ezis eht oge na evah I

Reversed quotes in reversed direction. As with, you cannot use any parameters with the   procedure.

First and last positions in the vector
Whether you're using cursors or the index, sometimes you're going to need to identify the beginning and/or the end of a vector. For this specific job, we have 4 methods available. Lets take a look at them.

Vectors.First_Index
Here's the specification for :

The benefits of using  (besides clarity) are not readily apparent unless we create a few vectors with different   parameters. I'll show the full source here, as the changes required are extensive:

The output from this program is:

0 0 I have an ego the size of a small planet. 1 My name is Linus Torvalds and I am your god. 2 Do you pine for the days when men were men and wrote their own device drivers? 3 If you need more than 3 levels of indentation, you're screwed anyway, and should fix your program. 4 You know you're brilliant, but maybe you'd like to understand what you did 2 weeks from now. 5 An infinite number of monkeys typing into GNU emacs would never make a good program. 6 Is "I hope you all die a painful death" too strong? 7 Most days I wake up thinking I'm the luckiest bastard alive. 8 I'm always right. This time I'm just even more right than usual. 9 And what's the internet without the rick-roll? 42 42 I have an ego the size of a small planet. 43 My name is Linus Torvalds and I am your god. 44 Do you pine for the days when men were men and wrote their own device drivers? 45 If you need more than 3 levels of indentation, you're screwed anyway, and should fix your program. 46 You know you're brilliant, but maybe you'd like to understand what you did 2 weeks from now. 47 An infinite number of monkeys typing into GNU emacs would never make a good program. 48 Is "I hope you all die a painful death" too strong? 49 Most days I wake up thinking I'm the luckiest bastard alive. 50 I'm always right. This time I'm just even more right than usual. 51 And what's the internet without the rick-roll? -100 -100 I have an ego the size of a small planet. -99 My name is Linus Torvalds and I am your god. -98 Do you pine for the days when men were men and wrote their own device drivers? -97 If you need more than 3 levels of indentation, you're screwed anyway, and should fix your program. -96 You know you're brilliant, but maybe you'd like to understand what you did 2 weeks from now. -95 An infinite number of monkeys typing into GNU emacs would never make a good program. -94 Is "I hope you all die a painful death" too strong? -93 Most days I wake up thinking I'm the luckiest bastard alive. -92 I'm always right. This time I'm just even more right than usual. -91 And what's the internet without the rick-roll?

Note how the number preceeding all the quotes is set accordingly to the subtype used as  for the vector. You should always use the  function instead of the actual numeric value, mainly because it makes it possible to change the   later on, without having to search all your code for references to a hard-coded numeric value. It is much safer using.

Vectors.Last_Index
Here's the specification for :

is a bit of an oddball, as it returns a value of type, instead of the expected. Where the  function returns the first value of the   (0 for , 1 for   and so on),   returns the   constant if the vector is empty. This  constant is equal to , which of course puts it just outside the range of the.

Let's see how it works. Add this to the declarative part of the program:

And this to the body of the program:

And the output is:

9 -1

As you can see, the  function returns   for the   vector. We've instantiated this vector with a  as the , and as you might know, the   type has the range  , and 0 minus 1 equals.

To further prove this point, try adding these two  blocks to the body:

Now the output is:

9 -1  No_Index No_Index

In his excellent book Programming in Ada 2005 (ISBN 0321340787), John Barnes has this to say about it:

"Note that the irritating subtype has to be introduced to cope with end values."

I don't know if I'd call  irritating, but it is an oddity that you should be aware of and understand.

Vectors.First
Here's the specification for :

The  function returns a cursor pointing to the first element in a vector. As with, the primary reason for using   is to avoid having to hard-code the first value of the   in your program.

Add this to the declarative part of the  program:

And this to the body:

The output is:

I have an ego the size of a small planet. I have an ego the size of a small planet.

You should always use either  or   to identify the first position in a vector. You should never ever hard-code the numerical value of the first position, as such a method risks failing if you change the  for the vector.

Vectors.Last
Here's the specification for :

is much more straightforward than its sibling, simply because it doesn't have to handle the "irritating"   type. The  function simply returns a cursor pointing at the last element in a vector, or in case of an empty vector, it returns. Lets see how it works.

Add this to the declarative part of the  program:

And this to the body:

The output from this program is:

And what's the internet without the rick-roll? No Elements in vector

As you can see, when a vector is empty, the value of the cursor is set to. If you try to "read" a  cursor, a   is raised.

Next and previous with a cursor
We've already seen how to iterate a vector using,   and regular loops using the index, so I think it's about time we learn how to do it with cursors. For this we have the  and   methods available.

Vectors.Next
Here's the specification for :

Depending on taste and preference, you can choose between using the  function or the   procedure. They both do the same thing: Move the cursor to the next element in the vector. I will show both versions in the following example.

First add this to the declarative part of the program:

And the this to the body:

And the output is:

I have an ego the size of a small planet. My name is Linus Torvalds and I am your god. Do you pine for the days when men were men and wrote their own device drivers? No_Element

Hopefully further explaining is unnecessary.

Vectors.Previous
Here's the specification for :

Where the  methods move the cursor forward, the   methods move the cursor backwards. I'm confident this is well understood by all, so without further ado, lets see how  works in actual code.

Add this to the declarative part:

And this to the body:

And the output:

And what's the internet without the rick-roll? I'm always right. This time I'm just even more right than usual. Most days I wake up thinking I'm the luckiest bastard alive. I have an ego the size of a small planet. No_Element

There should be no surprises here.

Finding things
Finding out if a specific element is present in a vector or if a given position contains a value are fairly common tasks when working with vectors, hence a handful of valuable tools have been made available to us.

Vectors.Find_Index
Here's the specification for :

The  function is actually just a wrapper around a simple loop, where each element in the vector is compared to. There's nothing "magical" about it. It wont be any faster than a homegrown loop, but it will save you a few lines of code. searches the vector from  and forward. defaults to, in this case 0.

To see how it works, we must first add a few variables to the declarative part of our program:

And then add this to the body:

And finally the output:

No_Index 7 No_Index

There are three interesting things going on in this example:


 * is of type . This is necessary to cope with the   value.
 * Using the  parameter of   enables us to start the search at a specified index.
 * The  value is returned if no matching element is found.

Besides those three things, there's really not a whole lot more to say about.

Vectors.Find
On this example, you will find the  example from above, modified to work with. These two functions are so alike in usage and functionality, that it would be a complete waste of space to do any further explaining. So all you get is the specification and the example.

Here's the specification for :

Vectors.Reverse_Find_Index
is similar to, except it searches from   and backwards until it reaches the beginning of the vector or finds a match. On the Example Source page you will find the  example modified to reflect this.

The specification for  is astonishingly similar to  :

Vectors.Reverse_Find
is similar to, except it searches backwards from   until it reaches the beginning of the vector or finds a match. On the Example Source page you will find the  example modified to reflect this.

The specification for  is astonishingly similar to  :

Vectors.Contains
Here's the specification for :

With  you basically get   with a   return value instead of an , and actually the   function is just a thin wrapper around the   function. If you're working with very large vectors and you know that the element you're looking for is situated near the end of the vector, from a performance point of view, you're probably better off using a homegrown solution. I'll show you one such later.

But first lets try our hand at a little  example. Add this to the declaration:

And the body:

And finally the output:

Not found! Found!

As stated earlier,  searches the vector from start to end, but that might not be the best solution. Sometimes you know a piece of data is placed near the end of the vector, if it's there at all. In such a case, a  function that searches in reverse is what we're looking for. One such would be easy to do:. With  editions available for the two   functions, I find it odd that there isn't a Reverse_Contains function available. Luckily, as the preceding source shows, it is very easy to add it yourself.

Vectors.Has_Element
Here's the specification for :

enables you to check if a cursor identifies an element, or as the ARM say:

"Returns True if Position designates an element, and returns False otherwise."

So  enables you to check if a cursor is still pointing at a valid element in a vector. Remember that a cursor designates both a container and a position in the container. This means that a cursor can point to a position in a vector that no longer exists. Lets see how it's used. Add this to the declaration:

And now add this to the body:

And the output is:

-1 No Element! 9 Element! -1 No Element! 8 Element!

I've honestly never had any use for  while working with vectors, but that's probably because I hardly ever use cursors with vectors. With it is a different story though, as the only means of navigating a doubly linked list is by using cursors.

From index to cursor, and vice versa
Sometimes it's necessary to convert an index to a cursor or vice-versa. This is done using the aptly named  and   functions.

Vectors.To_Cursor
Here's the specification for :

I will show you how the above function works, even though it should be painfully obvious. First add this to the declarative part of the program:

And this to the body:

The resulting output from this program is:

My name is Linus Torvalds and I am your god. An infinite number of monkeys typing into GNU emacs would never make a good program. No_Element

The important thing to take away from this example, is the  part. If the given  is out of range, then   is returned.

Vectors.To_Index
Here's the specification for :

Above we took a quick look at how to convert  to a cursor; now we'll do the opposite: Going from a cursor to. This is done using the  function.

You can keep the declarative part from the  example, but replace the body with the following:

This is not exactly rocket science, but it is worth noting that  is "transformed" into   when   is called on a cursor which point at.

Vectors.Generic_Sorting
The vector package also contains facilities to sort the vector, in the form of the generic package, so there's no need to mess around with home-grown sorting routines. The sorting is done in ascending order. The specification for  looks like this:

In order to use these procedures, we will first need to instantiate the  package. This is done the obvious way:

Simply add the above to the declarative part of the  program, and you're good to go. In the following we will look at how to use the generic procedures to sort a vector.

Generic_Sorting.Sort
Here's the specification for :

Other than instantiating the  generic (see  Vectors.Generic_Sorting), we needn't specify anything else in the declarative part of the   program. Instead we'll jump straight to the body, where we add these few lines to see how sorting works:

The output from the program is:

An infinite number of monkeys typing into GNU emacs would never make a good program. And what's the internet without the rick-roll? Do you pine for the days when men were men and wrote their own device drivers? I have an ego the size of a small planet. I'm always right. This time I'm just even more right than usual. If you need more than 3 levels of indentation, you're screwed anyway, and should fix your program. Is "I hope you all die a painful death" too strong? Most days I wake up thinking I'm the luckiest bastard alive. My name is Linus Torvalds and I am your god. You know you're brilliant, but maybe you'd like to understand what you did 2 weeks from now.

And there you have it: A perfectly sorted  file. It just doesn't get any simpler than that.

Generic_Sorting.Is_Sorted
Here's the specification for :

Figuring out if a vector has or has not been sorted is done using this little gem of a function. It will return  TRUE if sorting has been done, and   FALSE if not. This is how it works:

The output from the program is:

We have no yet sorted the Quotes vector Now we have sorted the Quotes vector

I'm certain the above result came as no surprise to you.

But what happens if a vector is sorted and then a new element is added? Will  still return   TRUE? Add the following code to the above, and lets see:

Now the output looks like this:

We have no yet sorted the Quotes vector Now we have sorted the Quotes vector The vector is no longer sorted

As could be expected, the  function will return   FALSE if changes are made to the vector, but this is not actually done using an internal "flag" of some sorts. No, the FALSE value is found by simply iterating over the entire vector while checking if position i + 1 is lesser than position i. If this is the case, then  return   FALSE.

In case of large vectors, this is not very efficient. Given that, you should of course only use  if it's absolutely necessary.

Generic_Sorting.Merge
Here's the specification for :

is special. It merges  with   and leaves   empty. What is special is that it doesn't sort the resulting vector, which one might expect,  being a part of the. If you want  to result in a sorted vector, then you must have sorted both   and   prior to the   call.

Lets see how it works. Add this to the declarative part of the  program:

And this to the body:

The output from this program is:

An infinite number of monkeys typing into GNU emacs would never make a good program. And what's the internet without the rick-roll? Bar Do you pine for the days when men were men and wrote their own device drivers? Foo I have an ego the size of a small planet. I'm always right. This time I'm just even more right than usual. If you need more than 3 levels of indentation, you're screwed anyway, and should fix your program. Is "I hope you all die a painful death" too strong? Most days I wake up thinking I'm the luckiest bastard alive. My name is Linus Torvalds and I am your god. You know you're brilliant, but maybe you'd like to understand what you did 2 weeks from now. Length of Quotes: 0

Note how the contents of the two vectors are merged into the  vector and also that the   vector is empty after the merge. Lets delete the  line and see what happens:

An infinite number of monkeys typing into GNU emacs would never make a good program. And what's the internet without the rick-roll? Foo Bar Do you pine for the days when men were men and wrote their own device drivers? I have an ego the size of a small planet. I'm always right. This time I'm just even more right than usual. If you need more than 3 levels of indentation, you're screwed anyway, and should fix your program. Is "I hope you all die a painful death" too strong? Most days I wake up thinking I'm the luckiest bastard alive. My name is Linus Torvalds and I am your god. You know you're brilliant, but maybe you'd like to understand what you did 2 weeks from now. Length of Quotes: 0

As you can see, the  vector is no longer sorted.

When using  it is very important to remember this: Both the   and   vectors must be sorted prior to the   call, else you'll end up with an un-sorted vector as the result. (If that is all you want, then it's probably faster to use one of the following procedures: Append,  Insert,  Prepend. Or you could simply use the   function to get the job done.)

Concatenate using the & operator
As seen earlier, it is possible to join two vectors/vector elements using a number of different techniques, such as append,  prepend,  insert and  merge, but there's also the "&" operator. The specification for the "&" functions look like this:

You can concatenate one vector to another, an element to a vector, a vector to an element and finally two elements. All 4 functions return a vector.

Lets see how it works. Add this to the declarative part of the program:

And this to the body:

And the output is:

Foo 1

I have an ego the size of a small planet. My name is Linus Torvalds and I am your god. Do you pine for the days when men were men and wrote their own device drivers? If you need more than 3 levels of indentation, you're screwed anyway, and should fix your program. You know you're brilliant, but maybe you'd like to understand what you did 2 weeks from now. An infinite number of monkeys typing into GNU emacs would never make a good program. Is "I hope you all die a painful death" too strong? Most days I wake up thinking I'm the luckiest bastard alive. I'm always right. This time I'm just even more right than usual. And what's the internet without the rick-roll? Foo 1

Bar 1 Bar 2

Foo 0 Foo 1

While the "&" operator works exactly as expected, there is one caveat, which John Barnes explains in his Ada 2005 book:

"The result is the same but using "&" is less efficient because of the extra copying involved."

Lets try a small example, where we compare append and the & operator. First I'll show the "&" example in full:

Timing this on my computer, yields these results (average of 10 runs):

real   0m1.183s user   0m1.028s sys    0m0.156s

Now with append and  prepend:

Timing this yields these results (average of 10 runs):

real   0m0.247s user   0m0.244s sys    0m0.002s

If you care about performance, it is probably best to avoid using the "&" functions. As the simple benchmark shows, there are faster ways to concatenate vectors and/or vector elements than using "&".

The & operator Example Source

Equality
Checking for equality between two vectors is done using the "=" function. Two vectors are only considered equal if both vectors are equal in length and the elements of each index are completely the same.

To see how it works, we must add this to the declarative part of the program:

And this to the body:

And the result is:

Quotes and Foo are NOT equal Quotes and Foo are equal

This is of course as expected.

Equality Example Source

Specification
Index_Type Element_Type "" Left   Element_Type Right  Element_Type Boolean Preelaborate Vectors Extended_Index Index_Type Index_Type 1 Index_Type Index_Type 1 Index_Type  1 No_Index  Extended_Index  Extended_Index Vector Preelaborable_Initialization Vector Cursor Preelaborable_Initialization Cursor Empty_Vector  Vector No_Element  Cursor "" Left   Vector Right  Vector Boolean To_Vector Length  Count_Type  Vector To_Vector New_Item  Element_Type Length    Count_Type Vector "" Left   Vector Right  Vector Vector "" Left   Vector Right  Element_Type Vector "" Left   Element_Type Right  Vector Vector "" Left   Element_Type Right  Element_Type Vector Capacity Container  Vector  Count_Type Reserve_Capacity Container   Vector Capacity       Count_Type Length Container  Vector  Count_Type Set_Length Container   Vector Length         Count_Type Is_Empty Container  Vector  Boolean Clear Container   Vector To_Cursor Container Vector Index     Extended_Index Cursor To_Index Position  Cursor  Extended_Index Element Container  Vector Index      Index_Type Element_Type Element Position  Cursor  Element_Type Replace_Element Container   Vector Index          Index_Type New_Item       Element_Type Replace_Element Container   Vector Position       Cursor New_item       Element_Type Query_Element Container  Vector Index      Index_Type Process       Element   Element_Type Query_Element Position  Cursor Process      Element   Element_Type Update_Element Container   Vector Index          Index_Type Process       Element    Element_Type Update_Element Container   Vector Position        Cursor Process       Element    Element_Type Move Target   Vector Source   Vector Insert Container   Vector Before         Extended_Index New_Item       Vector Insert Container   Vector Before         Cursor New_Item       Vector Insert Container   Vector Before         Cursor New_Item       Vector Position      Cursor Insert Container   Vector Before         Extended_Index New_Item       Element_Type Count          Count_Type  1 Insert Container   Vector Before         Cursor New_Item       Element_Type Count          Count_Type  1 Insert Container   Vector Before         Cursor New_Item       Element_Type Position      Cursor Count          Count_Type  1 Insert Container   Vector Before         Extended_Index Count          Count_Type  1 Insert Container   Vector Before         Cursor Position      Cursor Count          Count_Type  1 Prepend Container   Vector New_Item       Vector Prepend Container   Vector New_Item       Element_Type Count          Count_Type  1 Append Container   Vector New_Item       Vector Append Container   Vector New_Item       Element_Type Count          Count_Type  1 Insert_Space Container   Vector Before         Extended_Index Count          Count_Type  1 Insert_Space Container   Vector Before         Cursor Position      Cursor Count          Count_Type  1 Delete Container   Vector Index          Extended_Index Count          Count_Type  1 Delete Container   Vector Position    Cursor Count          Count_Type  1 Delete_First Container   Vector Count          Count_Type  1 Delete_Last Container   Vector Count          Count_Type  1 Reverse_Elements Container   Vector Swap Container   Vector I              Index_Type J              Index_Type Swap Container   Vector I              Cursor J              Cursor First_Index Container  Vector  Index_Type First Container  Vector  Cursor First_Element Container  Vector  Element_Type Last_Index Container  Vector  Extended_Index Last Container  Vector  Cursor Last_Element Container  Vector  Element_Type Next Position  Cursor  Cursor Next Position   Cursor Previous Position  Cursor  Cursor Previous Position   Cursor Find_Index Container  Vector Item       Element_Type Index      Index_Type  Index_Type Extended_Index Find Container  Vector Item       Element_Type Position   Cursor  No_Element Cursor Reverse_Find_Index Container  Vector Item       Element_Type Index      Index_Type  Index_Type Extended_Index Reverse_Find Container  Vector Item       Element_Type Position   Cursor  No_Element Cursor Contains Container  Vector Item       Element_Type Boolean Has_Element Position  Cursor  Boolean Iterate Container  Vector Process       Position   Cursor Reverse_Iterate Container  Vector Process       Position   Cursor "" Left   Element_Type Right  Element_Type Boolean Generic_Sorting Is_Sorted Container  Vector  Boolean Sort Container   Vector Merge Target   Vector Source   Vector Generic_Sorting Vector Empty_Vector  Vector Cursor No_Element  Cursor AdaContainersVectors

Wikibook

 * Ada Programming
 * Ada Programming/Libraries
 * Ada Programming/Libraries/Ada
 * Ada Programming/Libraries/Ada.Containers

Ada 2005 Rationale

 * 8.2 Lists and vectors