comp.lang.ada
 help / color / mirror / Atom feed
* strings and multidimensional arrays
@ 2003-10-12  4:05 Andrew
  2003-10-12  5:24 ` Andrew
  2003-10-13 13:59 ` Rodrigo Garcia
  0 siblings, 2 replies; 15+ messages in thread
From: Andrew @ 2003-10-12  4:05 UTC (permalink / raw)


Is this possible:
Can I create a multi-dimensional array.. and then at say row (4) , 
column (5)  have an entirely new string built?

basically having a string within a multi-dimensional array...
?
and if this is possible what would be a good place to look for ideas on 
how to do this?
thanks
Andrew




^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: strings and multidimensional arrays
  2003-10-12  4:05 Andrew
@ 2003-10-12  5:24 ` Andrew
  2003-10-12  6:27   ` tmoran
  2003-10-12 14:16   ` Robert I. Eachus
  2003-10-13 13:59 ` Rodrigo Garcia
  1 sibling, 2 replies; 15+ messages in thread
From: Andrew @ 2003-10-12  5:24 UTC (permalink / raw)




Andrew wrote:
> Is this possible:
> Can I create a multi-dimensional array.. and then at say row (4) , 
> column (5)  have an entirely new string built?
> 
> basically having a string within a multi-dimensional array...
> ?
> and if this is possible what would be a good place to look for ideas on 
> how to do this?
> thanks
> Andrew
> 

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




^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: strings and multidimensional arrays
  2003-10-12  5:24 ` Andrew
@ 2003-10-12  6:27   ` tmoran
  2003-10-12 14:16   ` Robert I. Eachus
  1 sibling, 0 replies; 15+ messages in thread
From: tmoran @ 2003-10-12  6:27 UTC (permalink / raw)


> Can I create a multi-dimensional array.. and then at say row (4) ,
> column (5)  have an entirely new string built?
  A : array(1 .. 10, 1 .. 100) of string(1 .. 11);
is a 2D array of 11 character strings, and you can say:
  A(4,5) := "hello world";
In general you can have an n-dimensional array of whatever, where whatever
is a character, a string, a bounded string, an integer, a record, another
array, etc.  Take a look at www.adapower.com for links to books, paper
and online, and tutorials, and of course lots of source code you can
peruse for examples.



^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: strings and multidimensional arrays
  2003-10-12  5:24 ` Andrew
  2003-10-12  6:27   ` tmoran
@ 2003-10-12 14:16   ` Robert I. Eachus
  2003-10-12 19:34     ` Jeffrey Carter
  2003-10-12 21:01     ` Andrew
  1 sibling, 2 replies; 15+ messages in thread
From: Robert I. Eachus @ 2003-10-12 14:16 UTC (permalink / raw)


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




^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: strings and multidimensional arrays
  2003-10-12 14:16   ` Robert I. Eachus
@ 2003-10-12 19:34     ` Jeffrey Carter
  2003-10-13  0:02       ` Robert I. Eachus
  2003-10-12 21:01     ` Andrew
  1 sibling, 1 reply; 15+ messages in thread
From: Jeffrey Carter @ 2003-10-12 19:34 UTC (permalink / raw)


Robert I. Eachus wrote:

> 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;

This is along the lines of what I was going to suggest. I don't 
understand, though, why you wrapped the Contents record in the Element 
record. I would simply say

type Thing is array (Positive range <>, Positive range <>) of CT;

Since you're a language lawyer and I'm not, I guess I'm missing 
something here, and wonder what it is.

-- 
Jeff Carter
"I've got to stay here, but there's no reason
why you folks shouldn't go out into the lobby
until this thing blows over."
Horse Feathers
50




^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: strings and multidimensional arrays
  2003-10-12 14:16   ` Robert I. Eachus
  2003-10-12 19:34     ` Jeffrey Carter
@ 2003-10-12 21:01     ` Andrew
  1 sibling, 0 replies; 15+ messages in thread
From: Andrew @ 2003-10-12 21:01 UTC (permalink / raw)




Robert I. Eachus wrote:
> 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.
> 

in reality I'm not sure how I need to do it.. what I need is  this:


a multi-dimensional array that when any given location is found to be of 
the value 'P' that I can change that location in the array into a string 
or somehow "attach" a string in that location.. (probably worded poorly 
but hopefully gets the point across) .. and in this string are integer 
values, that can be accessed and changed as needed.

As I have been thinking about it.. I'm not sure that a string is a good 
thing to be using.. since with strings you access the information in the 
string in the reverse order of what you put the information in.

So I'll read through what you suggested and see if I can't get it to 
work in the format that I need.




^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: strings and multidimensional arrays
  2003-10-12 19:34     ` Jeffrey Carter
@ 2003-10-13  0:02       ` Robert I. Eachus
  2003-10-13  3:14         ` Jeffrey Carter
  0 siblings, 1 reply; 15+ messages in thread
From: Robert I. Eachus @ 2003-10-13  0:02 UTC (permalink / raw)


Jeffrey Carter wrote:

 > This is along the lines of what I was going to suggest. I don't
 > understand, though, why you wrapped the Contents record in the
 > Element record. I would simply say
 >
 > type Thing is array (Positive range <>, Positive range <>) of
 > Content;
 >
 > Since you're a language lawyer and I'm not, I guess I'm missing
 > something here, and wonder what it is.

You can't have an array of unconstrained records, and Content is an
unconstrained record type. (Try it.) Wrapper is a constrained type, even 
though it has an unconstrained record type within it.

Or I could just say that it was necessary magic. ;-)

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




^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: strings and multidimensional arrays
  2003-10-13  0:02       ` Robert I. Eachus
@ 2003-10-13  3:14         ` Jeffrey Carter
  2003-10-13 17:05           ` Robert I. Eachus
  0 siblings, 1 reply; 15+ messages in thread
From: Jeffrey Carter @ 2003-10-13  3:14 UTC (permalink / raw)


Robert I. Eachus wrote:

> You can't have an array of unconstrained records, and Content is an
> unconstrained record type. (Try it.) Wrapper is a constrained type, even 
> though it has an unconstrained record type within it.

I have. It works, at least with GNAT 3.15p. The following compiles:

package Test_Unconstrained_Record_Array is
    type Disc is (One, Two, Five);

    type Unconstrained_Record (D : Disc := One) is record
       case D is
       when One =>
          I : Integer;
       when Two =>
          C : Character;
       when Five =>
          F : Float;
       end case;
    end record;

    type Thing is array (Positive range <>, Positive range <>) of
    Unconstrained_Record;
end Test_Unconstrained_Record_Array;

> Or I could just say that it was necessary magic. ;-)

Is GNAT wrong, or is it unnecessary magic? I've been doing this since 
1984. I know you can't have an array of indefinite elements (an 
unconstrained array type, such as String, or a type with unknown 
discriminants), but unconstrained records types are not indefinite.

-- 
Jeff Carter
"Sons of a silly person."
Monty Python & the Holy Grail
02




^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: strings and multidimensional arrays
  2003-10-12  4:05 Andrew
  2003-10-12  5:24 ` Andrew
@ 2003-10-13 13:59 ` Rodrigo Garcia
  1 sibling, 0 replies; 15+ messages in thread
From: Rodrigo Garcia @ 2003-10-13 13:59 UTC (permalink / raw)


Create a multi-dimensional array of access to string:

procedure Multi is
   type String_Ptr is access String;
   type Multi_Array is array
      (Positive range <>, Positive range <>) of String_Ptr;

   A : Multi_Array (1..5, 1..5);
begin
   A (4, 5) := new String'("Hello World");
end Multi;

Rodrigo

"Andrew" <specter@chartermi.net> wrote in message
news:3F88D320.80706@chartermi.net...
> Is this possible:
> Can I create a multi-dimensional array.. and then at say row (4) ,
> column (5)  have an entirely new string built?
>
> basically having a string within a multi-dimensional array...
> ?
> and if this is possible what would be a good place to look for ideas on
> how to do this?
> thanks
> Andrew
>





^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: strings and multidimensional arrays
  2003-10-13  3:14         ` Jeffrey Carter
@ 2003-10-13 17:05           ` Robert I. Eachus
  2003-10-13 18:49             ` Martin Dowie
  2003-10-14  1:10             ` Jeffrey Carter
  0 siblings, 2 replies; 15+ messages in thread
From: Robert I. Eachus @ 2003-10-13 17:05 UTC (permalink / raw)


Jeffrey Carter wrote:

 > Is GNAT wrong, or is it unnecessary magic? I've been doing this since
 >  1984. I know you can't have an array of indefinite elements (an
 > unconstrained array type, such as String, or a type with unknown
 > discriminants), but unconstrained records types are not indefinite.

Very interesting.  I see no problem with your package as written, in
fact I see no problem created objects of the array type.  (The
discriminants will all be assigned the default value One.)  But I
expected that a record assignment to an element that changed the
discriminant would raise Constraint_Error.  However, when I created an
instance of your array type and assigned to it this is what I got (from 
GNAT):

----------------------------------------------------------------------
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Float_Text_IO;
procedure Disc_Test is

   package Test_Unconstrained_Record_Array is
     type Disc is (One, Two, Five);

     type Unconstrained_Record (D : Disc := One) is record
       case D is
       when One =>
          I : Integer;
       when Two =>
          C : Character;
       when Five =>
          F : Float;
       end case;
     end record;

     type Thing is array (Positive range <>, Positive range <>) of
                 Unconstrained_Record;

   end Test_Unconstrained_Record_Array;

   package TURA renames Test_Unconstrained_Record_Array;
   package TURA_IO is new Ada.Text_IO.Enumeration_IO(TURA.Disc);

   TT: TURA.Thing(1..5, 1..5);

begin

   TT(1,1) := (TURA.One, 1);
   TT(2,2) := (TURA.Two, '2');
   TT(5,5) := (TURA.Five, 5.0);
   for I in 1..5 loop
     Put(" TT(" & Integer'Image(I)(2) & ',' & Integer'Image(I)(2) & ") 
is ");
     Put("( D => "); TURA_IO.Put(TT(I,I).D);
     case TT(I,I).D is
       when TURA.One =>
         Put(" I =>"); Put(Integer'Image(TT(I,I).I));
       when TURA.Two =>
         Put(" C =>"); Put(Character'Image(TT(I,I).C));
       when TURA.Five =>
         Put(" I =>"); Ada.Float_Text_IO.Put(TT(I,I).F,2,1,0);
     end case;
     Put_Line(").");
   end loop;
end Disc_Test;

-----------------------------------------------------------------------------

E:\Ada\Test>disc_test
disc_test
  TT(1,1) is ( D => ONE I => 1).
  TT(2,2) is ( D => TWO C =>'2').
  TT(3,3) is ( D => ONE I => 2013340188).
  TT(4,4) is ( D => ONE I => 38010744).
  TT(5,5) is ( D => FIVE I => 5.0).

I'm not going to assert that this is wrong. That would be for the ARG as
a whole to do.  The key paragraphs of the standard are 3.6(14): "An 
array_type_definition defines an array type and its first subtype.
For each object of this array type, the number of indices, the type and
position of each index, and the subtype of the components are as in the
type definition[; the values of the lower and upper bounds for each
index belong to the corresponding index subtype of its type, except for
null arrays (see 3.6.1)]."  This is the paragraph that implicitly sets 
the discriminants for uninitialized components.

And 3.6(11): "Within the definition of a nonlimited composite type (or a 
limited composite type that later in its immediate scope becomes 
nonlimited -- see 7.3.1 and 7.5), if a component_definition contains the 
reserved word aliased and the type of the component is discriminated, 
then the nominal subtype of the component shall be constrained."

The first quote implies that the subtype of the components can't be 
changed, the second implies they can be unless the components are 
declared as aliased.  (Adding the wrapper type allows you to declare the 
components aliased.)  I'll wait to see what Bob Duff, Randy, and 
possibly Tucker have to say.  Certainly this is not documented as a 
change from Ada 83 in the AARM.  But even if it wasn't intended as 
legal, it is a nice feature. ;-)

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




^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: strings and multidimensional arrays
  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
  1 sibling, 1 reply; 15+ messages in thread
From: Martin Dowie @ 2003-10-13 18:49 UTC (permalink / raw)


"Robert I. Eachus" <rieachus@comcast.net> wrote in message
news:3F8ADB3D.5010000@comcast.net...
>      type Unconstrained_Record (D : Disc := One) is record

Isn't this the key line here? The default ("One") allows you to change it
late (as often
as you like). If you didn't have this, then you would have to provide a
value at
declaration and it would be 'fixed' for the life of the object.





^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: strings and multidimensional arrays
  2003-10-13 18:49             ` Martin Dowie
@ 2003-10-13 21:47               ` Mark Lorenzen
  0 siblings, 0 replies; 15+ messages in thread
From: Mark Lorenzen @ 2003-10-13 21:47 UTC (permalink / raw)


"Martin Dowie" <martin.dowie@btopenworld.com> writes:

> "Robert I. Eachus" <rieachus@comcast.net> wrote in message
> news:3F8ADB3D.5010000@comcast.net...
>>      type Unconstrained_Record (D : Disc := One) is record
>
> Isn't this the key line here? The default ("One") allows you to change it
> late (as often

Yes it is. If a record contains a variant_part and the discriminant
governing the variant_part has a default value, then it is allowed to
perform an assignment that changes the value of the discriminant and
therefore also the variant_part.

So the following is allowed:

procedure Option is
   type Optional_Integer (Defined : Boolean := False) is
      record
         case (Defined) is
            when True  => Value : Integer;
            when False => null;
         end case;
      end record;

   Integer_Value : Optional_Integer;

begin
   Integer_Value := Optional_Integer'(Defined => True, Value => 5);
   Integer_Value := Optional_Integer'(Defined => True, Value => 3);
   Integer_Value := Optional_Integer'(Defined => False);
end Option;

> as you like). If you didn't have this, then you would have to provide a
> value at
> declaration and it would be 'fixed' for the life of the object.

Also correct. The following is *not* legal:

procedure Option is
   type Optional_Integer (Defined : Boolean) is
      record
         case (Defined) is
            when True  => Value : Integer;
            when False => null;
         end case;
      end record;

   Integer_Value : Optional_Integer (Defined => True);

begin
   Integer_Value := Optional_Integer'(Defined => True, Value => 5);
   Integer_Value := Optional_Integer'(Defined => True, Value => 3);
   Integer_Value := Optional_Integer'(Defined => False);
end Option;

The last assignment will raise Constraint_Error.

I can't find the paragraph(s) in the ARM, but it is burried there
somewhere.

- Mark Lorenzen



^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: strings and multidimensional arrays
  2003-10-13 17:05           ` Robert I. Eachus
  2003-10-13 18:49             ` Martin Dowie
@ 2003-10-14  1:10             ` Jeffrey Carter
  2003-10-14 15:29               ` Robert I. Eachus
  1 sibling, 1 reply; 15+ messages in thread
From: Jeffrey Carter @ 2003-10-14  1:10 UTC (permalink / raw)


Robert I. Eachus wrote:

> E:\Ada\Test>disc_test
> disc_test
>  TT(1,1) is ( D => ONE I => 1).
>  TT(2,2) is ( D => TWO C =>'2').
>  TT(3,3) is ( D => ONE I => 2013340188).
>  TT(4,4) is ( D => ONE I => 38010744).
>  TT(5,5) is ( D => FIVE I => 5.0).

This is about what I expected. We could provide default values for I, C, 
and F, and avoid the "stack junk" values for I in (3,3) and (4,4). Or 
assigned an initial value to TT.

> I'm not going to assert that this is wrong. That would be for the ARG as
> a whole to do.  The key paragraphs of the standard are 3.6(14): "An 
> array_type_definition defines an array type and its first subtype.
> For each object of this array type, the number of indices, the type and
> position of each index, and the subtype of the components are as in the
> type definition[; the values of the lower and upper bounds for each
> index belong to the corresponding index subtype of its type, except for
> null arrays (see 3.6.1)]."  This is the paragraph that implicitly sets 
> the discriminants for uninitialized components.

Is the subtype of

X : Discriminated_Record;

the same as of

Y : Discriminated_Record (D => One);

? The discriminant of X can change; of Y cannot.


> The first quote implies that the subtype of the components can't be 
> changed, the second implies they can be unless the components are 
> declared as aliased.  (Adding the wrapper type allows you to declare the 
> components aliased.)  I'll wait to see what Bob Duff, Randy, and 
> possibly Tucker have to say.  Certainly this is not documented as a 
> change from Ada 83 in the AARM.  But even if it wasn't intended as 
> legal, it is a nice feature. ;-)

That's a consequence of aliased I hadn't encountered, and the wrapper 
trick is a good thing to know. I didn't realize I was getting into an 
area that would require attention from the ARG. It seems like a 
significant incompatability from Ada 83 not to allow assignment to 
"normal" unconstrained record components.

-- 
Jeff Carter
"When danger reared its ugly head, he bravely
turned his tail and fled."
Monty Python and the Holy Grail
60




^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: strings and multidimensional arrays
@ 2003-10-14  6:24 christoph.grein
  0 siblings, 0 replies; 15+ messages in thread
From: christoph.grein @ 2003-10-14  6:24 UTC (permalink / raw)
  To: comp.lang.ada

> Very interesting.  I see no problem with your package as written, in
> fact I see no problem created objects of the array type.  (The
> discriminants will all be assigned the default value One.)  But I
> expected that a record assignment to an element that changed the
> discriminant would raise Constraint_Error.  However, when I created an
> instance of your array type and assigned to it this is what I got (from 
> GNAT):
> 
> ----------------------------------------------------------------------
> with Ada.Text_IO; use Ada.Text_IO;
> with Ada.Float_Text_IO;
> procedure Disc_Test is
> 
>    package Test_Unconstrained_Record_Array is
>      type Disc is (One, Two, Five);
> 
>      type Unconstrained_Record (D : Disc := One) is record
>        case D is
>        when One =>
>           I : Integer;
>        when Two =>
>           C : Character;
>        when Five =>
>           F : Float;
>        end case;
>      end record;
> 
>      type Thing is array (Positive range <>, Positive range <>) of
>                  Unconstrained_Record;
> 
>    end Test_Unconstrained_Record_Array;
> 
>    package TURA renames Test_Unconstrained_Record_Array;
>    package TURA_IO is new Ada.Text_IO.Enumeration_IO(TURA.Disc);
> 
>    TT: TURA.Thing(1..5, 1..5);
> 
> begin
> 
>    TT(1,1) := (TURA.One, 1);
>    TT(2,2) := (TURA.Two, '2');
>    TT(5,5) := (TURA.Five, 5.0);
>    for I in 1..5 loop
>      Put(" TT(" & Integer'Image(I)(2) & ',' & Integer'Image(I)(2) & ") 
> is ");
>      Put("( D => "); TURA_IO.Put(TT(I,I).D);
>      case TT(I,I).D is
>        when TURA.One =>
>          Put(" I =>"); Put(Integer'Image(TT(I,I).I));
>        when TURA.Two =>
>          Put(" C =>"); Put(Character'Image(TT(I,I).C));
>        when TURA.Five =>
>          Put(" I =>"); Ada.Float_Text_IO.Put(TT(I,I).F,2,1,0);
>      end case;
>      Put_Line(").");
>    end loop;
> end Disc_Test;
> 
> -----------------------------------------------------------------------------
> 
> E:\Ada\Test>disc_test
> disc_test
>   TT(1,1) is ( D => ONE I => 1).
>   TT(2,2) is ( D => TWO C =>'2').
>   TT(3,3) is ( D => ONE I => 2013340188).
>   TT(4,4) is ( D => ONE I => 38010744).
>   TT(5,5) is ( D => FIVE I => 5.0).
> 
> I'm not going to assert that this is wrong. That would be for the ARG as
> a whole to do.  The key paragraphs of the standard are 3.6(14): "An 
> array_type_definition defines an array type and its first subtype.
> For each object of this array type, the number of indices, the type and
> position of each index, and the subtype of the components are as in the
> type definition[; the values of the lower and upper bounds for each
> index belong to the corresponding index subtype of its type, except for
> null arrays (see 3.6.1)]."  This is the paragraph that implicitly sets 
> the discriminants for uninitialized components.
> 
> And 3.6(11): "Within the definition of a nonlimited composite type (or a 
> limited composite type that later in its immediate scope becomes 
> nonlimited -- see 7.3.1 and 7.5), if a component_definition contains the 
> reserved word aliased and the type of the component is discriminated, 
> then the nominal subtype of the component shall be constrained."
> 
> The first quote implies that the subtype of the components can't be 
> changed, the second implies they can be unless the components are 
> declared as aliased.  (Adding the wrapper type allows you to declare the 
> components aliased.)  I'll wait to see what Bob Duff, Randy, and 
> possibly Tucker have to say.  Certainly this is not documented as a 
> change from Ada 83 in the AARM.  But even if it wasn't intended as 
> legal, it is a nice feature. ;-)

I think here the language lawyer is in error (even gurus aren't infallible ;-). 
This has already been legal in 
Ada83, a wrapper was never needed.



^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: strings and multidimensional arrays
  2003-10-14  1:10             ` Jeffrey Carter
@ 2003-10-14 15:29               ` Robert I. Eachus
  0 siblings, 0 replies; 15+ messages in thread
From: Robert I. Eachus @ 2003-10-14 15:29 UTC (permalink / raw)


Jeffrey Carter wrote:

> That's a consequence of aliased I hadn't encountered, and the wrapper 
> trick is a good thing to know. I didn't realize I was getting into an 
> area that would require attention from the ARG. It seems like a 
> significant incompatability from Ada 83 not to allow assignment to 
> "normal" unconstrained record components.

And given the aliased rule, which works fine with the wrapper type but 
not with discriminated component, I think GNAT's behavior is as it 
should be.  It is just that to the exent that this behavior is changed 
from Ada 83, I would have expected it to be documented as such.  The 
rule for aliased components may be a change from Ada 83, but the 
presence of aliased is all the documentation needed for that.  But the 
rule for unaliased components may have implicitly changed here. Again it 
might be considered an extention, not a change, and as such not needed 
documentation.
-- 
                                           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




^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2003-10-14 15:29 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-10-14  6:24 strings and multidimensional arrays christoph.grein
  -- strict thread matches above, loose matches on Subject: below --
2003-10-12  4:05 Andrew
2003-10-12  5:24 ` Andrew
2003-10-12  6:27   ` tmoran
2003-10-12 14:16   ` Robert I. Eachus
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

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