comp.lang.ada
 help / color / mirror / Atom feed
From: Matthew Heaney <matthewjheaney@earthlink.net>
Subject: Re: OO Style with Ada Containers
Date: Mon, 19 Nov 2007 02:24:50 +0000
Date: 2007-11-19T02:24:50+00:00	[thread overview]
Message-ID: <u1wandlal.fsf@earthlink.net> (raw)
In-Reply-To: 1195086265.070953.93180@d55g2000hsg.googlegroups.com

braver <deliverable@gmail.com> writes:

> As you can see, I've managed to do prefix notation everywhere except
> cursors.  How do they coexist with prefix notation -- or are they
> replaced by something cooler already, too?  :)

No, cursors aren't tagged because an operation can only be primitive for a
single tagged type, and the container type is already tagged.


> I'd appreciate any improvements to the above, which I deduced from ARM
> and Rosetta Stone examples in an hour and then prefix'ised thanks to
> Adam's hint!  (Well I've followed Ada since 1987 so the spirit is easy
> to follow...)

The problem with your code is here:

   Ngram_Cursor := Ngram_Counts.Find(s);

   if not Has_Element(Ngram_Cursor) then
       Ngram_Counts.Insert(s, 1);
       New_Word_Count := New_Word_Count + 1;
   else -- a valid position in Ngram_Pos
       Count := Element(Ngram_Cursor);
       Ngram_Counts.Replace_Element(Ngram_Cursor, Count+1);
  end if;


The issue is that Find duplicates the search that must already be performed by
Insert. You don't want to be doing this if the map has many elements.

The solution is to use the conditional form of Insert, which does an atomic
search-and-insert and reports back the result of the search.  If the key is
already in the map, the cursor returned designates the existing key/element
pair (which is not modified); if the key is not in the map, the key/element
pair is inserted and the cursor passed back designates the newly-inserted pair.

What you do here is insert a count of 0 for the word, and then increment the
count. If the word is already in the map, the existing count is increment.  If
the word is not already in the map, the count is 0, so it gets incremented to
the value 1 (which is the desired value).

I have included an example program below.  Also included is a simple scanner
that returns a lexeme for each whitespace-delimited word on a line of text.

Feel free to write if you have any comments or questions.

Regards,
Matt


--STX
with Ada.Command_Line;  use Ada.Command_Line;
with Ada.Text_IO;  use Ada.Text_IO;
with Ada.Integer_Text_IO;  use Ada.Integer_Text_IO;
with Scanners;     use Scanners;
with Ada.Containers.Indefinite_Hashed_Maps;  use Ada.Containers;
with Ada.Strings.Hash_Case_Insensitive;
with Ada.Strings.Equal_Case_Insensitive;  use Ada.Strings;

procedure Count_Words is
   Line      : String (1 .. 256);
   Line_Last : Natural;

   package Map_Types is new Indefinite_Hashed_Maps
     (String,
      Natural,
      Hash_Case_Insensitive,
      Equal_Case_Insensitive);
   
   M : Map_Types.Map;
   use Map_Types;

   F : File_Type;

begin
   Open (F, In_File, Argument (1));

   while not End_Of_File (F) loop
      Get_Line(F, Line, Line_Last);

      declare
         procedure Increment_Count 
           (Word  : String; 
            Count : in out Natural)
         is
         begin
            Count := Count + 1;
         end;

         S : Scanner := Scan (Line (Line'First .. Line_Last));
         
         C : Map_Types.Cursor;
         B : Boolean;

      begin
         while S.Has_Word loop
            M.Insert (S.Word, 0, C, B);
            M.Update_Element (C, Increment_Count'Access);
         end loop;
      end;
   end loop;

   declare
      procedure Process (C : Map_Types.Cursor) is
         Word  : constant String := Key (C);
         Count : constant Natural := Element (C);

      begin
         Put (Word);
         Put (':');
         Put (Count, Width => 0);
         New_Line;
      end Process;

   begin
      M.Iterate (Process'Access);
   end;

end Count_Words;

package Scanners is
   pragma Pure;

   type Scanner (<>) is tagged limited private;

   function Scan (Line : String) return Scanner;

   function Has_Word (S : Scanner) return Boolean;
   function Word (S : Scanner) return String;

private

   type Handle (S : not null access Scanner) is limited null record;

   type Scanner (Last : Natural) is tagged limited record
      H          : Handle (Scanner'Access);
      Line       : String (1 .. Last);
      Word_First : Positive;
      Word_Last  : Natural;
   end record;

end Scanners;

with Ada.Characters.Latin_1;  use Ada.Characters;

package body Scanners is

   function Is_Whitespace (C : Character) return Boolean is
   begin
      case C is
         when ' ' | Latin_1.HT => 
            return True;
         when others =>
            return False;
      end case;
   end Is_Whitespace;
      

   procedure Next (S : in out Scanner) is
      I : Integer renames S.Word_First;
      J : Integer renames S.Word_Last;
      
   begin
      I := J + 1;
      while I <= S.Last 
        and then Is_Whitespace (S.Line (I))
      loop
         I := I + 1;
      end loop;
      
      if I > S.Last then
         return;  -- no more words on this line
      end if;
      
      J := I;
      while J < S.Last 
        and then not Is_Whitespace (S.Line (J + 1))
      loop
         J := J + 1;
      end loop;
   end Next;
      

   function Scan (Line : String) return Scanner is
   begin
      return S : Scanner (Line'Length) do
        S.Line := Line;
        -- S.Word_First := 1;
        S.Word_Last := 0;
        Next (S);
      end return;
   end Scan;


   function Has_Word (S : Scanner) return Boolean is
   begin
      return S.Word_First <= S.Word_Last;
   end Has_Word;


   function Word (S : Scanner) return String is
      L : constant Positive := S.Word_Last - S.Word_First + 1;
      
   begin
      return Result : String (1 .. L) do
        Result := S.Line (S.Word_First .. S.Word_Last);
        Next (S.H.S.all);
      end return;
   end Word;

end Scanners;



  parent reply	other threads:[~2007-11-19  2:24 UTC|newest]

Thread overview: 66+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-11-14 23:28 OO Style with Ada Containers braver
2007-11-14 23:50 ` Adam Beneschan
2007-11-14 23:59   ` braver
2007-11-15  0:24     ` braver
2007-11-15  9:36       ` Ludovic Brenta
2007-11-15 10:36         ` braver
2007-11-15 11:35           ` Ludovic Brenta
2007-11-15 13:50             ` braver
2007-11-19  2:45               ` Matthew Heaney
2007-11-15 18:22             ` braver
2007-11-15 20:18               ` Ludovic Brenta
2007-11-19  2:48                 ` Matthew Heaney
2007-11-19  2:47               ` Matthew Heaney
2007-11-19  2:39             ` Matthew Heaney
2007-11-19  2:38           ` Matthew Heaney
2007-11-19  2:36         ` Matthew Heaney
2007-11-19  2:24       ` Matthew Heaney [this message]
2007-11-23 10:28         ` braver
2007-11-23 13:29           ` Martin Krischik
2007-11-23 14:19             ` Georg Bauhaus
2007-11-25 13:38           ` Ludovic Brenta
2007-11-26  3:58             ` Matthew Heaney
2007-11-26  3:55           ` Matthew Heaney
2007-11-23 22:25         ` braver
2007-11-23 22:46           ` Pascal Obry
2007-11-23 22:52             ` braver
2007-11-26  4:09               ` Matthew Heaney
2007-11-26  4:07             ` Matthew Heaney
2007-11-26  4:03           ` Matthew Heaney
2007-11-26 13:45             ` Matthew Heaney
2007-11-26 19:09               ` braver
2007-11-26 20:29                 ` Matthew Heaney
2007-11-27 19:31                   ` Georg Bauhaus
2007-11-27 20:12                     ` Matthew Heaney
2007-11-25 14:08         ` braver
2007-11-26  4:21           ` Matthew Heaney
2007-11-19  1:04   ` Matthew Heaney
2007-11-15  8:43 ` Dmitry A. Kazakov
2007-11-15 14:04   ` Maciej Sobczak
2007-11-19  2:53     ` Matthew Heaney
2007-11-19 13:44       ` Maciej Sobczak
2007-11-19 14:44         ` Martin
2007-11-19 15:51         ` Matthew Heaney
2007-11-19 17:33           ` Markus E L
2007-11-19 21:29           ` Maciej Sobczak
2007-11-19 22:16             ` Matthew Heaney
2007-11-19 22:22               ` Matthew Heaney
2007-11-20 14:11               ` Maciej Sobczak
2007-11-20 17:00                 ` Matthew Heaney
2007-11-20 17:17                   ` Matthew Heaney
2007-11-20 21:13                   ` Maciej Sobczak
2007-11-20 21:57                     ` Matthew Heaney
2007-11-21  4:51                     ` Matthew Heaney
2007-11-21  9:18                       ` Georg Bauhaus
2007-11-21 15:59                         ` Maciej Sobczak
2007-11-21 17:41                           ` Georg Bauhaus
2007-11-21 22:25                         ` Jeffrey R. Carter
2007-11-20 18:06                 ` Georg Bauhaus
2007-11-19 16:19         ` Dmitry A. Kazakov
2007-11-19 20:45           ` Maciej Sobczak
2007-11-20  2:24             ` Matthew Heaney
2007-11-20  9:06             ` Dmitry A. Kazakov
2007-11-20 12:16               ` Georg Bauhaus
2007-11-21 15:17                 ` Dmitry A. Kazakov
2007-11-19  2:50   ` Matthew Heaney
2007-11-19  1:03 ` Matthew Heaney
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox