text:
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 — 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


text:
Ada Programming/Packages

Ada encourages the division of code into separate modules called packages. Each package can contain any combination of items.

Some of the benefits of using packages are:
 * package contents are placed in a separate namespace, preventing naming collisions,
 * implementation details of the package can be hidden from the programmer (information hiding),
 * object orientation requires defining a type and its primitive subprograms within a package, and
 * packages that are library units can be separately compiled.

Some of the more common package usages are:
 * a group of related subprograms along with their shared data, with the data not visible outside the package,
 * one or more data types along with subprograms for manipulating those data types, and
 * a generic package that can be instantiated under varying conditions.

The following is a quote from the current Ada Reference Manual

"Packages are program units that allow the specification of groups of logically related entities. Typically, a package contains the declaration of a type (often a private type or private extension) along with the declaration of primitive subprograms of the type, which can be called from outside the package, while their inner workings remain hidden from outside users."

Separate compilation
Note: The following chapters deal with packages on library level. This is the most common use, since packages are the basic code structuring means in Ada. However, Ada being a block oriented language, packages can be declared at any level in any declarative region. In this case, the normal visibility rules apply, also for the package body.

Package specifications and bodies on library level are compilation units, so can be separately compiled. Ada has nothing to say about how and where compilation units are stored. This is implementation dependent. (Most implementations indeed store compilation units in files of their own; name suffixes vary, GNAT uses  and , APEX   and  .) The package body can itself be divided into multiple parts by specifying that subprogram implementations or bodies of nested packages are separate. These are then further compilation units.

One of the biggest advantages of Ada over most other programming languages is its well-defined system of modularization and separate compilation. Even though Ada allows separate compilation, it maintains the strong type checking among the various compilations by enforcing rules of compilation order and compatibility checking. Ada compilers determine the compilation sequence; no make file is needed. Ada uses separate compilation (like Modula-2, Java and C#), and not independent compilation (as C/C++ does), in which the various parts are compiled with no knowledge of the other compilation units with which they will be combined.

A note to C/C++ users: Yes, you can use the preprocessor to emulate separate compilation — but it is only an emulation and the smallest mistake leads to very hard to find bugs. It is telling that all C/C++ successor languages including D have turned away from the independent compilation and the use of the preprocessor.

So it's good to know that Ada has had separate compilation ever since Ada-83 and is probably the most sophisticated implementation around.

Parts of a package
A package generally consists of two parts, the specification and the body. A package specification can be further divided in two logical parts, the visible part and the private part. Only the visible part of the specification is mandatory. The private part of the specification is optional, and a package specification might not have a package body—the package body only exists to complete any incomplete items in the specification. Subprogram declarations are the most common incomplete items. There must not be a package body if there is no incomplete declaration, and there has to be a package body if there is some incomplete declaration in the specification.

To understand the value of the three-way division, consider the case of a package that has already been released and is in use. A change to the visible part of the specification will require that the programmers of all using software verify that the change does not affect the using code. A change to the private part of the declaration will require that all using code be recompiled but no review is normally needed. Some changes to the private part can change the meaning of the client code however. An example is changing a private record type into a private access type. This change can be done with changes in the private part, but change the semantic meaning of assignment in the clients code. A change to the package body will only require that the file containing the package body be recompiled, because nothing outside of the package body can ever access anything within the package body (beyond the declarations in the specification part).

A common usage of the three parts is to declare the existence of a type and some subprograms that operate on that type in the visible part, define the actual structure of the type (e.g. as a record) in the private part, and provide the code to implement the subprograms in the package body.

The package specification — the visible part
The visible part of a package specification describes all the subprogram specifications, variables, types, constants etc. that are visible to anyone who wishes to use the package.

Public_Only_Package Range_10  1 .. 10; Public_Only_Package;

Since Range_10 is an integer type, there are a lot of operations declared implicitly in this package.

The private part
The private part of a package serves two purposes:
 * To complete the deferred definition of private types and constants.
 * To export entities only visible to the children of the package.

Package_With_Private Private_Type ; Private_Type  (1 .. 10)  Integer; Package_With_Private;

Since the type is private, clients cannot make any use of it as long as there are no operations defined in the visible part.

The package body
The package body defines the implementation of the package. All the subprograms defined in the specification have to be implemented in the body. New subprograms, types and objects can be defined in the body that are not visible to the users of the package. Package_With_Body Basic_Record ; Set_A (This :  Basic_Record;                     An_A :      Integer); Get_A (This : Basic_Record) Integer; Basic_Record A : Integer; ;     (Get_A);  -- not a standard Ada pragma (Get_A); (Set_A); Package_With_Body;

Package_With_Body Set_A (This :  Basic_Record;                     An_A :      Integer) This.A := An_A; Set_A; Get_A (This : Basic_Record) Integer This.A;    Get_A; Package_With_Body;

 * : Only available when using GNAT.

Two Flavors of Package
The packages above each define a type together with operations of the type. When the type's composition is placed in the private part of a package, the package then exports what is known to be an Abstract Data Type or ADT for short. Objects of the type are then constructed by calling one of the subprograms associated with the respective type.

A different kind of package is the Abstract State Machine or ASM. A package will be modeling a single item of the problem domain, such as the motor of a car. If a program controls one car, there is typically just one motor, or the motor. The public part of the package specification only declares the operations of the module (of the motor, say), but no type. All data of the module are hidden in the body of the package where they act as state variables to be queried, or manipulated by the subprograms of the package. The initialization part sets the state variables to their initial values.

Package_With_Body Set_A An_A  Integer Get_A Integer Pure_Function Get_A—not a standard Ada pragma Package_With_Body

Package_With_Body The_A Integer Set_A An_A  Integer The_A An_A Set_A Get_A Integer The_A Get_A The_A 0 Package_With_Body

(A note on construction: The package initialization part after corresponds to a construction subprogram of an ADT package. However, as a state machine is an “object” already, “construction” is happening during package initialization. (Here it sets the state variable The_A to its initial value.) An ASM package can be viewed as a singleton.)

Using packages
To utilize a package it's needed to name it in a with clause, whereas to have direct visibility of that package it's needed to name it in a use clause.

For C++ programmers, Ada's with clause is analogous to the C++ preprocessor's #include and Ada's use is similar to the using namespace statement in C++. In particular, use leads to the same namespace pollution problems as using namespace and thus should be used sparingly. Renaming can shorten long compound names to a manageable length, while the use type clause makes a type's operators visible. These features reduce the need for plain use.

Standard with
The standard with clause provides visibility for the public part of a unit to the following defined unit. The imported package can be used in any part of the defined unit, including the body when the clause is used in the specification.

Private with
Ada.Strings.Unbounded; Private_With Basic_Record ; Set_A (This :  Basic_Record;                     An_A :      String); Get_A (This : Basic_Record) String; Unbounded Ada.Strings.Unbounded; Basic_Record A : Unbounded.Unbounded_String; ;     (Get_A); (Get_A); (Set_A); Private_With;

Private_With Set_A (This :  Basic_Record;                     An_A :      String) This.A := Unbounded.To_Unbounded_String (An_A); Set_A; Get_A (This : Basic_Record) String Unbounded.To_String (This.A); Get_A; Private_With;

Limited with
The limited with can be used to represent two mutually dependent type (or more) located in separate packages.

Departments; Employees Employee  ; Assign_Employee (E :  Employee;       D :  Departments.Department'); Dept_Ptr   Departments.Department'; Current_Department(E : Employee)  Dept_Ptr; ... Employees;

Employees; Departments Department  ; Choose_Manager (Dept   :   Department;       Manager :  Employees.Employee'); ... Departments;

Making operators visible
Suppose you have a package Universe that defines some numeric type T.

Universe P   V UniverseT  100 V V  420 P

This program fragment is illegal since the operators implicitly defined in Universe are not directly visible.

You have four choices to make the program legal.

Use a use_package_clause. This makes all declarations in Universe directly visible (provided they are not hidden because of other homographs).

Universe Universe P   V UniverseT  100 V V  420 P

Use renaming. This is error prone since if you rename many operators, cut and paste errors are probable.

Universe P    "*" Left Right UniverseT  UniverseT  Universe"*" "/" Left Right UniverseT UniverseT  Universe"*" V UniverseT 100 V V  420 P

Use qualification. This is extremely ugly and unreadable.

Universe P   V UniverseT  100 V Universe"*" V 420 P

Use the use_type_clause. This makes only the operators in Universe directly visible.

Universe P   V UniverseT  100 UniverseT V V  420 P

There is a special beauty in the use_type_clause. Suppose you have a set of packages like so:

Universe Pack T UniverseT Pack

Pack P   V PackT  100 V V  420 P

Now you've got into trouble. Since Universe is not made visible, you cannot use a use_package_clause for Universe to make the operator directly visible, nor can you use qualification for the same reason. Also a use_package_clause for Pack does not help, since the operator is not defined in Pack. The effect of the above construct means that the operator is not nameable, i.e. it cannot be renamed in a renaming statement.

Of course you can add Universe to the context clause, but this may be impossible due to some other reasons (e.g. coding standards); also adding the operators to Pack may be forbidden or not feasible. So what to do?

The solution is simple. Use the use_type_clause for Pack.T and all is well!

Pack P   V PackT  100 PackT V V  420 P

Nested packages
A nested package is a package declared inside a package. Like a normal package, it has a public part and a private part. From outside, items declared in a nested package N will have visibility as usual; the programmer may refer to these items using a full dotted name like . (But not .)

P    D Integer N       X Integer Foo Integer N   E Integer M       Y Integer Bar Integer M P

Inside a package, declarations become visible as they are introduced, in textual order. That is, a nested package N that is declared after some other declaration D can refer to this declaration D. A declaration E following N can refer to items of N. But neither can “look ahead” and refer to any declaration that goes after them. For example, spec  above cannot refer to   in any way.

In the following example, a type is derived in both of the two nested packages Disks and Books. Notice that the full declaration of parent type Item appears before the two nested packages.

Shelf Elaborate_Body ID  1_000  9_999 Item Identifier ID           Item_Ref    Item Next_ID ID     Disks Music Jazz Rock Raga Classic Pop Soul Disk Style Music Identifier  ID   Item Identifier Artist Unbounded_String Title  Unbounded_String Disks Books Literature Play Novel Poem Story Text Art Book Kind Literature Identifier  ID   Item Identifier Authors Unbounded_String Title   Unbounded_String Year    Integer Books Put it Item_Ref Get identifier ID  Item_Ref Search title String  ID     Boxes TreasureIdentifier ID          TreasureIdentifier ID   ItemIdentifier Boxes Shelf

A package may also be nested inside a subprogram. In fact, packages can be declared in any declarative part, including those of a block.

Child packages
Ada allows one to extend the functionality of a unit (package) with so-called children (child packages). With certain exceptions, all the functionality of the parent is available to a child. This means that all public and private declarations of the parent package are visible to all child packages. The above example, reworked as a hierarchy of packages, looks like this. Notice that the package is not needed by the top level package Shelf, hence its with clause doesn't appear here. (We have added a match function for searching a shelf, though):

Shelf Elaborate_Body ID  1_000  9_999 Item Identifier ID           Item_Ref    Item Next_ID ID     match it  Item Text  String  Boolean Put it Item_Ref Get identifier ID  Item_Ref Search title String  ID  Shelf

The name of a child package consists of the parent unit's name followed by the child package's identifier, separated by a period (dot) `'.

ShelfBooks Literature Play Novel Poem Story Text Art Book Kind Literature Identifier  ID   Item Identifier Authors Unbounded_String Title   Unbounded_String Year    Integer matchit Book text String Boolean ShelfBooks

Book has two components of type Unbounded_String, so appears in a with clause of the child package. This is unlike the nested packages case which requires that all units needed by any one of the nested packages be listed in the context clause of the enclosing package (see ). Child packages thus give better control over package dependences. With clauses are more local.

The new child package Shelf.Disks looks similar. The <tt>Boxes</tt> package which was a nested package in the private part of the original <tt>Shelf</tt> package is moved to a private child package:

ShelfBoxes TreasureIdentifier ID        TreasureIdentifier ID   ItemIdentifier matchit Treasure text String Boolean ShelfBoxes

The privacy of the package means that it can only be used by equally private client units. These clients include private siblings and also the bodies of siblings (as bodies are never public).

Child packages may be listed in context clauses just like normal packages. A of a child also 'withs' the parent.

Subunits
A subunit is just a feature to move a body into a place of its own when otherwise the enclosing body will become too large. It can also be used for limiting the scope of context clauses.

The subunits allow to physically divide a package into different compilation units without breaking the logical unity of the package. Usually each separated subunit goes to a different file allowing separate compilation of each subunit and independent version control history for each one.

Pack Proc Pack Some_Unit Pack Proc ...  Proc

Wikibook

 * Ada Programming

Wikipedia

 * Module

Ada 2005 Reference Manual

|Packages Packages

Programación en Ada/Paquetes

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/

title: Ada Programming/Packages


text:
Ada Programming/Libraries

Predefined Language Libraries
Ada's built-in library is provided by three root library units: Ada, Interfaces, and System; other library units are children of these. The library is quite extensive and well-structured. These chapters too are more reference like. Most specifications included in them have been obtained from the reznikmm/adalib repository.

The package Standard contains all predefined identifiers in the language.

 * Standard
 * Ada
 * Interfaces
 * System

Ada 83 had a much smaller library and did not yet have this library structure. These root libraries were introduced in Ada 95 to inhibit a name pollution. To preserve compatibility, there exist renamings of all Ada 83 library units  as   respectively  ; see RM. Contrary to the names in the root hierarchies, the original Ada 83 names  are not protected – they may be reused for user-defined library units.

Implementation-Defined Language Libraries
Every Ada implementation has as an extension of the predefined Ada library. One example is the library provided by the GNAT implementation.

 * GNAT

Other Language Libraries
Other libraries which are not part of the standard but freely available.

 * Multi Purpose
 * Container Libraries
 * GUI Libraries
 * Distributed Objects
 * Database
 * Web Programming
 * Input/Output

Wikibook

 * Ada Programming

Resources

 * A collection of Tools and Libraries maintained by the Ada Resource Association.
 * The collection of crates of Alire, a package manager for Ada libraries and applications in source form.

|Libraries

Programación en Ada/Unidades predefinidas

title: Ada Programming/Libraries


text:
User:The bellman/Proof

Abstract
Wikipedia, an international project that uses Wiki software to collaboratively create an encyclopaedia, is becoming more and more popular. Everyone can directly edit articles and every edit is recorded. The version history of all articles is freely available and allows a multitude of examinations. This research-in-progress paper gives an overview on Wikipedia research. Wikipedia’s fundamental components that are articles, authors, edits, and links are analysed as well as content and quality. Possibilities of research are explored including examples and first results. Several characteristics that are found in Wikipedia, such as exponential growth and scale-free networks, structures which are all known in other contexts however the Wiki architecture also possesses some intrinsic specialities. General trends are measured that are typical for all Wikipedias but vary between languages in detail.

Conclusions
There is still little research about Wikipedia and Wikis. This research-in-progress paper presented a first overview on Wikipedia research. After a linear phase, Wikipedias grow exponentially with different rates per language. The growth rate of the number of articles is typically smaller than other ratios. Different Wikipedias can be compared with simple methods such as counting growth rates, namespaces and article types. Article sizes are lognormal distributed with a linear growing median. For articles with 5 or more distinct authors its number follows a power law as well as the number of distinct articles per author. More detailed methods for measuring edits exist. Because every Wikipedia article covers a single concept and links to related ones, you can derive thesaurus-like structures out of the network of articles. The network is scale-free on internal links, external links and broken links. There are many possibilities for deeper investigation, especially regarding quality and content. Like Wikimedia itself, its research is in the very beginning but very promising.

title: User:The bellman/Proof


text:
Movie Making Manual/Storyboarding

Storyboards are drawings of the sequence of shots for a script. It helps to pre-visualize how the director wants the screenplay to be shot. As an image says more than a thousand words it is very useful as a basis to communicate the director's ideas to the crew and the producers. Some directors will storyboard every scene and camera angle to save time and money when they are on set. Others however feel that this can inhibit their creativity and will have very few graphic representations done before shooting commences.

Getting Started
To get an idea of how you can storyboard your movie, grab a comic book off the shelf at a bookstore. Many large productions will have storyboards that are somewhere between stick-man quality and full comic book illustrations. If you can draw fairly well yourself, it may seem tedious, but you will gain a lot from trying to draw out a few of the most complex sequences. Every time you storyboard you will take that moment to see the shot through the camera. It's a heck of a lot less expensive than having a cast and crew waiting for you to "discover your vision" right there on the spot.

For the definitions of some of the concepts please refer to cinematography. Storyboarding is mainly there to get a first idea of what the film will look like. It gives indications of the size of the shot, the camera angle and the sequence of the shots. It is rarely followed exactly but it is a helpful guideline during the shooting of a film. It's very common while a crew is tearing down all the lighting rigs and moving to the next shot, the Director and DP will be looking at the storyboard trying decide what is best before everything needs to be placed. Since they have those plans, they are more capable of improvising.

The main areas where storyboarding is regarded as essential are in the planning of elaborate stunts, special effects sequences and designing make-up and costumes.

Animatic
An animatic is a movie which has been edited from the storyboards. Animatics are useful for determining the timing of a shot, particularly an expensive shot such as an effects shot.

Software
1. Thumbnails are storyboards no bigger than a thumbnail. There is little detail in thumbnail storyboards. Each person's head is represented by a circle. Thumbnails are done with pencil and paper.

2. There are 2D storyboard programs such as StoryBoard Quick and StoryBoard Artist. They are fast ways to make high quality storyboards.

3. There are 3D storyboarding programs such as FrameForge 3D Studio, Antics (which is no longer in business) and SketchUp Pro. Designed for creating storyboards, these programs can be faster than the other kinds of 3D animation software. Free limited demo versions of FrameForge 3D Studio and SketchUp are available.

4. There are many kinds of 3D animation programs which work for creating accurate shots such as Blender 3d, Maya, 3D Studio Max, Cinema4d and Lightwave 3D. There is a free version of Maya for non-commercial use called Personal Learning Edition.

5. There are specialized 3D animation programs such as Poser and DAZ Studio (freeware) which use 3D figures called digital puppets or Poser models. Use predefined figures is much faster than creating your own figures. Digital puppets that work with Poser and DAZ studio are inexpensive ($12 to $100). The advantage of creating storyboards with these programs is you can use the same lens that the camera will use. That can be valuable for effects shots.

6. If you are storyboarding for 3D animation, there is a program called Redboard which allows you to quickly draw in 2D over accurate 3d models, then export your cameras to Maya. A valuable time-saver if you're thinking about working in 3D.

Lessons in Storyboarding

 * Wikiversity offers a free lesson in creating storyboarding for a short motion picture. There are also new lessons for 3D storyboarding.

/Writing movies /Directing /Pre-production /Scheduling

title: Movie Making Manual/Storyboarding


text:
Robotics/Components/Actuation Devices/Shape Memory Alloys

Here is a good introduction about what Shape Memory Alloys (SMA) are.

The main use of SMA in robotics is to imitate human muscles. One of the better known SMAs is Nitinol wire. It contracts about 5 to 7% of its length and consumes a lot of power.

One of the most popular nitinol driven robots is Stiquito.


text:
Robotics/Components/Actuation Devices/Piezoelectric Actuators

Piezoelectric actuators are actuators that take advantage of the piezoelectric effect found in certain materials.

Piezoelectric Effect

Certain materials have a characteristic of generating an electric potential when compressed or expanded. The amount of potential across the surface is determined by the force of displacement.

Because an electric potential is created from a change in volume, a change in temperature also has the ability of generating an electric potential.

The piezoelectric effect also has an inverse effect. When a voltage is applied to a material with piezoelectric properties, the material expands or contracts depending on the polarity of the voltage applied. The inverse piezoelectric effect is the basis of piezoelectric motors.

Materials with the Piezoelectric properties
Piezoelectricity naturally occurs in symmetrical crystals. Piezoelectric materials can also be manufactured as ceramics.

Crystals Ceramics " All Crap"
 * Quartz
 * Tourmaline
 * Barium Titanate

More Materials can be found by going here, and filtering for the piezoelectric category.

Piezoelectric Actuators
The ability to change shape when a voltage is applied can be used to displace objects. This basically allows electrical energy to be converted to mechanical energy. This can be used to rotate motors or even

Linear
The concept behind a linear piezo motor is layering a stack of piezoelectric discs that will push on each other and eventually push on a surface at an angle which will propel the object forward. The distance the propeller pushes is limited, but the frequency can be very rapid. The input voltage can change the output speed and allows a great amount of accurate movements. The force exerted is minimal and lessens the worry of breaking smaller objects.

Rotary
A rotary motor can work in the same fashion as the linear motor, except when you apply this concept at a much steeper angle to an axle, the linear motion is turned into a rotational motion. Two of these linear motors applied on both sides of a disc in the same direction can spin the disc. This is the same concept in a pitching machine used to sling baseballs.

Stepper
Using a piezoelectric material for a stepper motor can give you better precision due to the short distances involved. By placing piezoelectric motors in opposing directions operating at frequencies that are slightly out-of-phase, the rotation is slight between the time when piezoelectric motors have the disc in a “hold” state. The slight movements and rapid response allow the rotation to be precise.

Squiggle Motor
New Scale Technologies has taken this concept and applied it to a nut and bolt to create a type of screwing effect. The vibrations caused by the piezoelectric material cause the nut to exhibit a “hula hoop” effect to the threads, moving the screw up or downward depending on polarity. This can be used to push an object on a small scale very accurately.

Robotics Applications
Piezoelectric motors have the benefit of being very precise at very fast frequencies. They can also operate on a very small scale allowing robots to become smaller. Piezoelectric motors have the benefit of being able to exert a large displacement with a low driving voltage. Another benefit is the minimal amount of EMI/RFI noise created.

They can be wired in such a way to be sensors as well. They can be used to determine the number of rotations, or if there is a force being exerted against a surface.