I was trying to find out if the standard Ada libraries come equipped with a "dictionary" type (by which I mean: a data structure that stores values in a <key, value>
format from which I can retrieve a value
by using the corresponding unique key
).
Does such data structure exist? If so, can someone provide a working example of how to populate and query it?
I tried searching on Google but it just comes up with hundreds of results from online dictionaries that define the word "ada".
Another word for Dictionary is Map; a Map provides a mapping from a key to a value.
Ada.Containers has two distinct kinds of Map, Hashed and Ordered. For the Hashed map, you provide a hash function on the Key type, while for the Ordered map you provide a comparison function “<“ to define the order.
Further to this, each of those kinds comes in two forms, definite and indefinite. Definite types are, broadly, those where the compiler knows the size of objects of the type, so that it can reserve the correct amount of space in the Container for the contained objects to be stored directly - such as Integer - whereas for indefinite types such as String the runtime size can change from instance to instance, so that the Container has to use dynamic allocation behind the scenes.
I had a requirement to count the number of times a named subprogram had been entered, and used this as the basis:
package String_To_Count_Maps
is new Ada.Containers.Indefinite_Hashed_Maps
(Element_Type => Natural,
Key_Type => String,
Hash => Ada.Strings.Hash_Case_Insensitive,
Equivalent_Keys => Ada.Strings.Equal_Case_Insensitive);
(there was no need to supply an equality operation for Natural
, since the standard “=“ is defaulted).
I declare the map:
Saved_Entries : String_To_Count_Maps.Map;
and then I can increment the current count for For_Subprogram_Named
by
...
C : constant String_To_Count_Maps.Cursor :=
Saved_Entries.Find (For_Subprogram_Named);
use type String_To_Count_Maps.Cursor;
begin
if C = String_To_Count_Maps.No_Element then
Saved_Entries.Insert (For_Subprogram_Named, 1);
else
Saved_Entries.Replace_Element
(Position => C,
New_Item => String_To_Count_Maps.Element (C) + 1); -- see (a)
end if;
The code for extracting the current count has similarly to account for the case where there haven’t been any “increments” yet.
(a) You’ll notice that, because Map
is a tagged type and Cursor
isn’t, I can say things like Saved_Entries.Replace_Element (...)
, but not C.Element + 1
. This is annoying, but I’m told There Are Reasons.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With