comp.lang.ada
 help / color / mirror / Atom feed
From: "Robert I. Eachus" <rieachus@comcast.net>
Subject: Re: strings and multidimensional arrays
Date: Sun, 12 Oct 2003 14:16:38 GMT
Date: 2003-10-12T14:16:38+00:00	[thread overview]
Message-ID: <3F89621F.7070406@comcast.net> (raw)
In-Reply-To: 3F88E586.5060809@chartermi.net

Andrew wrote:
>  
> hopefully I don't confuse the situation by adding this, but...
> 
> my problem is this .. on a multi-dimensional array .. at any given point 
> in that array I can only have on piece of data (ex: blue or X or 65 or 
> some other value.. but only one piece of data) I need to store multiple 
> pieces of data ..
> 
> I'm hoping that when that point on the multi-dimensional array is called 
> or looked at, that I can put a string there so in essense I will have 
> multiple pieces of data running off of that point.. (if that makes sense).

It can be done, and in fact done pretty cleanly.  However, it sounds 
like that is not really what you want to do, but a workaround for the 
solution you really want.

It sounds like what you would prefer is something like this:

type Contents_Type is (None, Integer_Data, Some_String, 
Integer_and_String, Subprogram_Access, ...);

type Contents(CT: Contents_Type := None) is record
   case CT is
     when None => null;
     when Integer_Data => I: Integer;
     when Some_String => U: Ada.Strings.Unbounded.Unbounded_String;
     when Integer_and_String =>
       The_Integer: Integer;
       The_String: Ada.Strings.Unbounded.Unbounded_String;
     when Subprogram_Access => FP: Function_Pointer;
     when ...
   end case;
end record;

type Element is record
    C: Contents := (CT => None);
end record;

type My_Array is array(Natural range <>; Natural range <>) of Element;
...

A few words of wisdom. If this really is what you want.

1) Keep the actual contents small. That is why I used Unbounded_String 
above.  It will result in a pointer to the actual data in the record 
type, and the actual data being stored on the heap. (The Unbound_String 
type will manage the heap storage for the individual values, so you 
never have to write an allocator or deallocator.)

The Ada compiler is almost certainly going to "allocate the max," allow 
room in every entry for the largest entry.  (I believe the Alsys 
compiler still supports "mutant" records.  That would allow you to use 
String for individual components.  But it doesn't come for free.  The 
compiler manages the mutant type without coding effort on your part, but 
it still results in extra code, and the overhead of executing it.)

2) Given the above, and that most Ada compilers (and operating systems) 
allow you to have a much bigger heap than stack, you may want to store 
any actual arrays of this type on the heap.  That is, create an access 
type that points to one of these arrays, and call new (once) to create 
the array.

3) You will probably want to make the actual type an abstract data type
and put the real declarations in the private part of a package, along 
with access functions, etc.

4) If you do this, one of the operations you will want for the abstract 
data type is a function that displays the contents, of a cell, including 
the discriminant.

5) In the variant part(s), if you take this approach, every component 
list has to have unique names.  But you can have multiple variant parts. 
  So if you have several Contents_Type for which you want say to have an 
integer, you could say inside the record declaration:

    case CT is
       when Integer_Data | Integer_and_String =>
          I: Integer;
       when others => null;
    end case;

    case CT is
       when Some_String | Integer_and_String =>
          S: Ada.Strings.Unbounded.Unbounded_String;
       when others => null;
    end case;

    case CT is...

Of course, if you do this, making the type an ADT is almost a necessity. 
  You don't want to deal with unwrapping things in more than one place, 
and you will want "inquiry" functions like:

     function Contains_Integer (E: Element) return Boolean;

5) Having the Ada Reference Manual handy while you work on this is a 
good idea.  An up-to-date version on-line can be found at:
http://www.adaic.org/standards/95lrm/html/RM-TOC.html

6) Another approach is to use a tagged type, and have an array of access 
values of an access to classwide type.  I'll let someone else describe 
that approach.  But the important thing to remember is that if you do 
put all this in a package with Element as a private type, you can switch 
between implementations just by replacing the package.  (The decision on 
whether or not to make the array type private is up to you.  I wouldn't, 
  I'd just hide the details of the various parts of Element.  But see 
the next item.)

7) Design first!  This is a useful pattern to know.  The tagged type 
approach is a different way to approach the problem.  If the 
multidimensional array is expected to be sparsely populated there are 
other approaches.  In fact, if what you are really trying to do is store 
data where the presence or absence of each field type is independent, 
you may be better off with separate arrays for each datatype.  Either of 
those cases argues for making the array type abstract as well, and 
making the array accesses implicit.  If you do a lot of thinking, and 
perhaps even write the application that will use the type before 
defining the type itself, you can save a lot of coding effort.

8) Good luck.

-- 
                                          Robert I. Eachus

"Quality is the Buddha. Quality is scientific reality. Quality is the 
goal of Art. It remains to work these concepts into a practical, 
down-to-earth context, and for this there is nothing more practical or 
down-to-earth than what I have been talking about all along...the repair 
of an old motorcycle."  -- from Zen and the Art of Motorcycle 
Maintenance by Robert Pirsig




  parent reply	other threads:[~2003-10-12 14:16 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-10-12  4:05 strings and multidimensional arrays Andrew
2003-10-12  5:24 ` Andrew
2003-10-12  6:27   ` tmoran
2003-10-12 14:16   ` Robert I. Eachus [this message]
2003-10-12 19:34     ` Jeffrey Carter
2003-10-13  0:02       ` Robert I. Eachus
2003-10-13  3:14         ` Jeffrey Carter
2003-10-13 17:05           ` Robert I. Eachus
2003-10-13 18:49             ` Martin Dowie
2003-10-13 21:47               ` Mark Lorenzen
2003-10-14  1:10             ` Jeffrey Carter
2003-10-14 15:29               ` Robert I. Eachus
2003-10-12 21:01     ` Andrew
2003-10-13 13:59 ` Rodrigo Garcia
  -- strict thread matches above, loose matches on Subject: below --
2003-10-14  6:24 christoph.grein
replies disabled

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