Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a "dictionary" type pre-implemented in Ada? And how to use it?

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".

like image 399
Master_T Avatar asked Jul 23 '14 17:07

Master_T


1 Answers

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.

like image 131
Simon Wright Avatar answered Oct 16 '22 01:10

Simon Wright