From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,FREEMAIL_FROM autolearn=ham autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,3957a46660bc0588 X-Google-Attributes: gid103376,public X-Google-ArrivalTime: 2003-10-12 07:16:39 PST Path: archiver1.google.com!news2.google.com!news.maxwell.syr.edu!wn14feed!wn13feed!worldnet.att.net!204.127.198.203!attbi_feed3!attbi_feed4!attbi.com!sccrnsc02.POSTED!not-for-mail Message-ID: <3F89621F.7070406@comcast.net> From: "Robert I. Eachus" User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.0.2) Gecko/20021120 Netscape/7.01 X-Accept-Language: en-us, en MIME-Version: 1.0 Newsgroups: comp.lang.ada Subject: Re: strings and multidimensional arrays References: <3F88D320.80706@chartermi.net> <3F88E586.5060809@chartermi.net> Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit NNTP-Posting-Host: 24.34.139.183 X-Complaints-To: abuse@comcast.net X-Trace: sccrnsc02 1065968198 24.34.139.183 (Sun, 12 Oct 2003 14:16:38 GMT) NNTP-Posting-Date: Sun, 12 Oct 2003 14:16:38 GMT Organization: Comcast Online Date: Sun, 12 Oct 2003 14:16:38 GMT Xref: archiver1.google.com comp.lang.ada:734 Date: 2003-10-12T14:16:38+00:00 List-Id: 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