comp.lang.ada
 help / color / mirror / Atom feed
* Array of records with default values not propagating to array
@ 2018-02-03 11:06 Bojan Bozovic
  2018-02-03 14:16 ` Jere
                   ` (3 more replies)
  0 siblings, 4 replies; 13+ messages in thread
From: Bojan Bozovic @ 2018-02-03 11:06 UTC (permalink / raw)


When I defined a record, and set a default value for some of its components, these don't propagate when I make array of these records. Here is code that can be compiled, but I wonder do I need to explicitly assign value for 'others' in 'Initialize' procedure. This has nothing to do with Ada random number generation, I might have as well used Ada.Numerics.Float_Random, or the reusable code that was posted in another thread, with the same result, so I will post in this separate thread. When I omit "others =>" in Initialize, I get compilation errors at these lines both on FSF compiler and AdaCore GPL compiler on Windows. Is this intended behavior or I am missing something?

with Ada.Numerics.Discrete_Random;
with Ada.Text_IO;
with Ada.Text_IO.Unbounded_IO;
with Ada.Strings;
with Ada.Strings.Unbounded;

procedure Tarot1 is

Maximum_Deck_Length: constant integer := 78;
subtype Card_Position is Positive range 1..Maximum_Deck_Length;
type Card_Suits is (Cups,Pentacles,Swords,Wands);
type Trump_Values is new Natural range 0..21;
type Card_Values is (Two,Three,Four,Five,Six,Seven,Eight,Nine,Ten,Page,Knight,Queen,King,Ace);
type Card_Info (Trump: Boolean := False) is record
-- we will skip giving name and divinatory meaning to cards - its just ordinary assignment but for each card separately;
-- PROBLEM: Assignment here does nothing, so I have to assign these values in Initialize procedure below as well

Name : Ada.Strings.Unbounded.Unbounded_String := Ada.Strings.Unbounded.Null_Unbounded_String;
Divinatory_Meaning: Ada.Strings.Unbounded.Unbounded_String := Ada.Strings.Unbounded.Null_Unbounded_String;

case Trump is 
	when True => Trump_Value:Trump_Values;
	when False =>  Card_Value:Card_Values;
					Suit_Value:Card_Suits;
end case;
end record;
type Deck is array (Card_Position) of Card_Info;
package Card_Position_Random is new Ada.Numerics.Discrete_Random (Result_Subtype => Card_Position);

procedure Initialize ( TDeck : in out Deck) is
	Index: Card_Position := 1;
	begin
		-- first lay 22 trump cards in a deck
			for Index_1 in Trump_Values loop
			TDeck (Index) := (Trump => True, Trump_Value => Index_1, others => Ada.Strings.Unbounded.Null_Unbounded_String);
			Index := Index + 1;
			end loop;
		-- now lay 4 suits of 14 cards each;
		for Suit_Index in Card_Suits loop
			for Card_Index in Card_Values loop
			TDeck (Index) := (Trump => False, Card_Value => Card_Index, Suit_Value => Suit_Index, others => Ada.Strings.Unbounded.Null_Unbounded_String);
			exit when Index=Maximum_Deck_Length; -- preventing CONSTRAINT_ERROR;
			Index:=Index+1;
			end loop;
			end loop;
end Initialize;

   procedure Shuffle (TDeck : in out Deck) is
      Position_Gen   : Card_Position_Random.Generator;
      Temporary_Data : Card_Info;
      Index_Random   : Card_Position;
   begin
      Card_Position_Random.Reset (Gen => Position_Gen);
      for Index in Card_Position loop
         Index_Random         := Card_Position_Random.Random (Gen => Position_Gen);
         Temporary_Data       := TDeck (Index);
         TDeck (Index)        := TDeck (Index_Random);
         TDeck (Index_Random) := Temporary_Data;
      end loop;
   end Shuffle;
   Tarot_Deck : Deck;
   begin
   Initialize(Tarot_Deck);
   Shuffle(Tarot_Deck);
   for Index in Card_Position loop -- just print the deck as shuffled
   if Tarot_Deck(Index).Trump then
	Ada.Text_IO.Put_Line("Major Arcana/Trump: "&Trump_Values'Image(Tarot_Deck(Index).Trump_Value));
else
	Ada.Text_IO.Put_Line("Minor Arcana: "&Card_Values'Image(Tarot_Deck(Index).Card_Value)&" of "&Card_Suits'Image(Tarot_Deck(Index).Suit_Value));
	end if;
	end loop;
   end Tarot1;

Thanks for help.



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

* Re: Array of records with default values not propagating to array
  2018-02-03 11:06 Array of records with default values not propagating to array Bojan Bozovic
@ 2018-02-03 14:16 ` Jere
  2018-02-03 14:54   ` Bojan Bozovic
  2018-02-03 15:26   ` Simon Wright
  2018-02-04  2:43 ` Robert Eachus
                   ` (2 subsequent siblings)
  3 siblings, 2 replies; 13+ messages in thread
From: Jere @ 2018-02-03 14:16 UTC (permalink / raw)


On Saturday, February 3, 2018 at 6:06:52 AM UTC-5, Bojan Bozovic wrote:
> When I defined a record, and set a default value for some of its components, these don't propagate when I make array of these records. Here is code that can be compiled, but I wonder do I need to explicitly assign value for 'others' in 'Initialize' procedure. This has nothing to do with Ada random number generation, I might have as well used Ada.Numerics.Float_Random, or the reusable code that was posted in another thread, with the same result, so I will post in this separate thread. When I omit "others =>" in Initialize, I get compilation errors at these lines both on FSF compiler and AdaCore GPL compiler on Windows. Is this intended behavior or I am missing something?
> 
> with Ada.Numerics.Discrete_Random;
> with Ada.Text_IO;
> with Ada.Text_IO.Unbounded_IO;
> with Ada.Strings;
> with Ada.Strings.Unbounded;
> 
> procedure Tarot1 is
> 
> Maximum_Deck_Length: constant integer := 78;
> subtype Card_Position is Positive range 1..Maximum_Deck_Length;
> type Card_Suits is (Cups,Pentacles,Swords,Wands);
> type Trump_Values is new Natural range 0..21;
> type Card_Values is (Two,Three,Four,Five,Six,Seven,Eight,Nine,Ten,Page,Knight,Queen,King,Ace);
> type Card_Info (Trump: Boolean := False) is record
> -- we will skip giving name and divinatory meaning to cards - its just ordinary assignment but for each card separately;
> -- PROBLEM: Assignment here does nothing, so I have to assign these values in Initialize procedure below as well
> 
> Name : Ada.Strings.Unbounded.Unbounded_String := Ada.Strings.Unbounded.Null_Unbounded_String;
> Divinatory_Meaning: Ada.Strings.Unbounded.Unbounded_String := Ada.Strings.Unbounded.Null_Unbounded_String;
> 
> case Trump is 
> 	when True => Trump_Value:Trump_Values;
> 	when False =>  Card_Value:Card_Values;
> 					Suit_Value:Card_Suits;
> end case;
> end record;
> type Deck is array (Card_Position) of Card_Info;
> package Card_Position_Random is new Ada.Numerics.Discrete_Random (Result_Subtype => Card_Position);
> 
> procedure Initialize ( TDeck : in out Deck) is
> 	Index: Card_Position := 1;
> 	begin
> 		-- first lay 22 trump cards in a deck
> 			for Index_1 in Trump_Values loop
> 			TDeck (Index) := (Trump => True, Trump_Value => Index_1, others => Ada.Strings.Unbounded.Null_Unbounded_String);
> 			Index := Index + 1;
> 			end loop;
> 		-- now lay 4 suits of 14 cards each;
> 		for Suit_Index in Card_Suits loop
> 			for Card_Index in Card_Values loop
> 			TDeck (Index) := (Trump => False, Card_Value => Card_Index, Suit_Value => Suit_Index, others => Ada.Strings.Unbounded.Null_Unbounded_String);
> 			exit when Index=Maximum_Deck_Length; -- preventing CONSTRAINT_ERROR;
> 			Index:=Index+1;
> 			end loop;
> 			end loop;
> end Initialize;
> 
>    procedure Shuffle (TDeck : in out Deck) is
>       Position_Gen   : Card_Position_Random.Generator;
>       Temporary_Data : Card_Info;
>       Index_Random   : Card_Position;
>    begin
>       Card_Position_Random.Reset (Gen => Position_Gen);
>       for Index in Card_Position loop
>          Index_Random         := Card_Position_Random.Random (Gen => Position_Gen);
>          Temporary_Data       := TDeck (Index);
>          TDeck (Index)        := TDeck (Index_Random);
>          TDeck (Index_Random) := Temporary_Data;
>       end loop;
>    end Shuffle;
>    Tarot_Deck : Deck;
>    begin
>    Initialize(Tarot_Deck);
>    Shuffle(Tarot_Deck);
>    for Index in Card_Position loop -- just print the deck as shuffled
>    if Tarot_Deck(Index).Trump then
> 	Ada.Text_IO.Put_Line("Major Arcana/Trump: "&Trump_Values'Image(Tarot_Deck(Index).Trump_Value));
> else
> 	Ada.Text_IO.Put_Line("Minor Arcana: "&Card_Values'Image(Tarot_Deck(Index).Card_Value)&" of "&Card_Suits'Image(Tarot_Deck(Index).Suit_Value));
> 	end if;
> 	end loop;
>    end Tarot1;
> 
> Thanks for help.

The big issue I see is not incrementing Index in the first loop.  As it
stands, you simply keep reassigning trumps to the same card over and over
again.  Since the type is uninitialized and the next for loop cannot fill
the deck, you get a constraint error later on in the print statement when
trying to print a minor arcana.  As a note, defaulting the variant portion
of the record definition did prevent the constraint error, though obviously
the results were wrong because Initialize did not initialize the whole deck.

Try:

with Ada.Numerics.Discrete_Random;
with Ada.Text_IO;
with Ada.Text_IO.Unbounded_IO;
with Ada.Strings;
with Ada.Strings.Unbounded; 

procedure Tarot1 is
   
   Maximum_Deck_Length: constant integer := 78;
   subtype Card_Position is Positive range 1..Maximum_Deck_Length;
   type Card_Suits is (Cups,Pentacles,Swords,Wands);
   type Trump_Values is new Natural range 0..21;
   type Card_Values is (Two,Three,Four,Five,Six,Seven,Eight,Nine,Ten,Page,Knight,Queen,King,Ace);
   type Card_Info (Trump: Boolean := False) is record
      -- we will skip giving name and divinatory meaning to cards - its just ordinary assignment but for each card separately;
      -- PROBLEM: Assignment here does nothing, so I have to assign these values in Initialize procedure below as well

      Name : Ada.Strings.Unbounded.Unbounded_String := Ada.Strings.Unbounded.Null_Unbounded_String;
      Divinatory_Meaning: Ada.Strings.Unbounded.Unbounded_String := Ada.Strings.Unbounded.Null_Unbounded_String;

      case Trump is
         when True =>
            Trump_Value:Trump_Values;
         when False =>
            Card_Value:Card_Values;
            Suit_Value:Card_Suits;
      end case;
   end record;
   type Deck is array (Card_Position) of Card_Info;
   package Card_Position_Random is new Ada.Numerics.Discrete_Random (Result_Subtype => Card_Position);

   procedure Initialize ( TDeck : in out Deck) is
      Index: Card_Position := 1;
   begin
      -- first lay 22 trump cards in a deck
      for Index_1 in Trump_Values loop
         TDeck (Index) := (Trump => True, Trump_Value => Index_1, others => <>);
         Index := Index + 1;  -- Jere:  I added this
      end loop;
      
      -- now lay 4 suits of 14 cards each;
      for Suit_Index in Card_Suits loop
         for Card_Index in Card_Values loop
            TDeck (Index) := (Trump => False, Card_Value => Card_Index, Suit_Value => Suit_Index, others => <>);
            exit when Index=Maximum_Deck_Length; -- preventing CONSTRAINT_ERROR;
            Index:=Index+1;
         end loop;
      end loop;
   end Initialize;

   procedure Shuffle (TDeck : in out Deck) is
      Position_Gen   : Card_Position_Random.Generator;
      Temporary_Data : Card_Info;
      Index_Random   : Card_Position;
   begin
      Card_Position_Random.Reset (Gen => Position_Gen);
      for Index in Card_Position loop
         Index_Random         := Card_Position_Random.Random (Gen => Position_Gen);
         Temporary_Data       := TDeck (Index);
         TDeck (Index)        := TDeck (Index_Random);
         TDeck (Index_Random) := Temporary_Data;
      end loop;
   end Shuffle;
   Tarot_Deck : Deck; 
   
begin
   
   Initialize(Tarot_Deck);
   Shuffle(Tarot_Deck);
   for Index in Card_Position loop -- just print the deck as shuffled
      Ada.Text_IO.put("Index = " & Card_Position'Image(Index) & " => ");
      if Tarot_Deck(Index).Trump then
         Ada.Text_IO.Put_Line("Major Arcana/Trump: "&Trump_Values'Image(Tarot_Deck(Index).Trump_Value));
      else
         Ada.Text_IO.Put_Line("Minor Arcana: "&Card_Values'Image(Tarot_Deck(Index).Card_Value)&" of "&Card_Suits'Image(Tarot_Deck(Index).Suit_Value));
      end if;
   end loop;
   
end Tarot1;

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

* Re: Array of records with default values not propagating to array
  2018-02-03 14:16 ` Jere
@ 2018-02-03 14:54   ` Bojan Bozovic
  2018-02-03 15:26   ` Simon Wright
  1 sibling, 0 replies; 13+ messages in thread
From: Bojan Bozovic @ 2018-02-03 14:54 UTC (permalink / raw)


Thanks for helping me learn the basics!


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

* Re: Array of records with default values not propagating to array
  2018-02-03 14:16 ` Jere
  2018-02-03 14:54   ` Bojan Bozovic
@ 2018-02-03 15:26   ` Simon Wright
  2018-02-03 16:07     ` Jere
  2018-02-04  9:21     ` Niklas Holsti
  1 sibling, 2 replies; 13+ messages in thread
From: Simon Wright @ 2018-02-03 15:26 UTC (permalink / raw)


Jere <jhb.chat@gmail.com> writes:

> The big issue I see is not incrementing Index in the first loop.  As
> it stands, you simply keep reassigning trumps to the same card over
> and over again.

When I copied OP's code it _did_ increment Index in the first loop. ??

I find that

   type Card_Info (Trump : Boolean := False) is record
      Name : Ada.Strings.Unbounded.Unbounded_String;
      Divinatory_Meaning : Ada.Strings.Unbounded.Unbounded_String;
      ...

         TDeck (Index) :=
           (Trump       => True,
            Trump_Value => Index_1,
            others      => <>);
         ...

            TDeck (Index) :=
              (Trump      => False,
               Card_Value => Card_Index,
               Suit_Value => Suit_Index,
               others     => <>);

compiles OK and seems to run perfectly well. Presumably this is OK
because the initial value for an otherwise-uninitialized unbounded
string is the empty string. Or maybe it's GNAT being over-helpful, since
it seems not to obey ARM 4.3.1(17.1)[1].

[1] http://www.ada-auth.org/standards/rm12_w_tc1/html/RM-4-3-1.html#p17.1


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

* Re: Array of records with default values not propagating to array
  2018-02-03 15:26   ` Simon Wright
@ 2018-02-03 16:07     ` Jere
  2018-02-04  9:21     ` Niklas Holsti
  1 sibling, 0 replies; 13+ messages in thread
From: Jere @ 2018-02-03 16:07 UTC (permalink / raw)


On Saturday, February 3, 2018 at 10:26:57 AM UTC-5, Simon Wright wrote:
> Jere writes:
> 
> > The big issue I see is not incrementing Index in the first loop.  As
> > it stands, you simply keep reassigning trumps to the same card over
> > and over again.
> 
> When I copied OP's code it _did_ increment Index in the first loop. ??
> 
That is weird.  I highlighted all and did a copy + paste into GPS. I guess
I accidentally deleted it somehow.  Sorry about that!


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

* Re: Array of records with default values not propagating to array
  2018-02-03 11:06 Array of records with default values not propagating to array Bojan Bozovic
  2018-02-03 14:16 ` Jere
@ 2018-02-04  2:43 ` Robert Eachus
  2018-02-04  4:59 ` Bojan Bozovic
  2018-02-04 10:19 ` Jeffrey R. Carter
  3 siblings, 0 replies; 13+ messages in thread
From: Robert Eachus @ 2018-02-04  2:43 UTC (permalink / raw)


On Saturday, February 3, 2018 at 6:06:52 AM UTC-5, Bojan Bozovic wrote:
> When I defined a record, and set a default value for some of its components, these don't propagate when I make array of these records.
> Thanks for help.

I could explain the rules that result in the need for the others part, but that won't help you move forward.  What I suggest is you first try commenting out the call to Shuffle, and see if you can print out your initial deck.

If so, replace the others with explicit initial values for the two Unbounded_Strings. (Or just temporarily comment out those fields in the declaration and the others.)

If that fixes it, fine.  Send a bug report to Ada_Core and go on with your life and code.

Note that if I were writing this code, I would shuffle a vector, then indirect through the vector to get the card values:
 
type Deck is array (Card_Position) of access Card_Info;

then Initialize assigns values to each.  (Need to change the two TDeck assignments to create new access values.) Now Shuffle swapping pointers instead of several variable length fields.  I think the only change necessary to Shuffle to do this is the declaration of Temporary_Data.

Is this worth doing now?  Only if there really is an GNAT bug and getting rid of the others doesn't fix it.  This is certainly an optimization worth considering after the program is running.

Oh one last detail which you may be leaving until later.  When using tarot decks it is usually important to know if the card is inverted or not.  Again something to add once the rest of it is working.

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

* Re: Array of records with default values not propagating to array
  2018-02-03 11:06 Array of records with default values not propagating to array Bojan Bozovic
  2018-02-03 14:16 ` Jere
  2018-02-04  2:43 ` Robert Eachus
@ 2018-02-04  4:59 ` Bojan Bozovic
  2018-02-04  9:34   ` Simon Wright
  2018-02-04 10:07   ` Niklas Holsti
  2018-02-04 10:19 ` Jeffrey R. Carter
  3 siblings, 2 replies; 13+ messages in thread
From: Bojan Bozovic @ 2018-02-04  4:59 UTC (permalink / raw)


On Saturday, February 3, 2018 at 12:06:52 PM UTC+1, Bojan Bozovic wrote:
> When I defined a record, and set a default value for some of its components, these don't propagate when I make array of these records. Here is code that can be compiled, but I wonder do I need to explicitly assign value for 'others' in 'Initialize' procedure. This has nothing to do with Ada random number generation, I might have as well used Ada.Numerics.Float_Random, or the reusable code that was posted in another thread, with the same result, so I will post in this separate thread. When I omit "others =>" in Initialize, I get compilation errors at these lines both on FSF compiler and AdaCore GPL compiler on Windows. Is this intended behavior or I am missing something?
> 
> with Ada.Numerics.Discrete_Random;
> with Ada.Text_IO;
> with Ada.Text_IO.Unbounded_IO;
> with Ada.Strings;
> with Ada.Strings.Unbounded;
> 
> procedure Tarot1 is
> 
> Maximum_Deck_Length: constant integer := 78;
> subtype Card_Position is Positive range 1..Maximum_Deck_Length;
> type Card_Suits is (Cups,Pentacles,Swords,Wands);
> type Trump_Values is new Natural range 0..21;
> type Card_Values is (Two,Three,Four,Five,Six,Seven,Eight,Nine,Ten,Page,Knight,Queen,King,Ace);
> type Card_Info (Trump: Boolean := False) is record
> -- we will skip giving name and divinatory meaning to cards - its just ordinary assignment but for each card separately;
> -- PROBLEM: Assignment here does nothing, so I have to assign these values in Initialize procedure below as well
> 
> Name : Ada.Strings.Unbounded.Unbounded_String := Ada.Strings.Unbounded.Null_Unbounded_String;
> Divinatory_Meaning: Ada.Strings.Unbounded.Unbounded_String := Ada.Strings.Unbounded.Null_Unbounded_String;
> 
> case Trump is 
> 	when True => Trump_Value:Trump_Values;
> 	when False =>  Card_Value:Card_Values;
> 					Suit_Value:Card_Suits;
> end case;
> end record;
> type Deck is array (Card_Position) of Card_Info;
> package Card_Position_Random is new Ada.Numerics.Discrete_Random (Result_Subtype => Card_Position);
> 
> procedure Initialize ( TDeck : in out Deck) is
> 	Index: Card_Position := 1;
> 	begin
> 		-- first lay 22 trump cards in a deck
> 			for Index_1 in Trump_Values loop
> 			TDeck (Index) := (Trump => True, Trump_Value => Index_1, others => Ada.Strings.Unbounded.Null_Unbounded_String);
> 			Index := Index + 1;
> 			end loop;
> 		-- now lay 4 suits of 14 cards each;
> 		for Suit_Index in Card_Suits loop
> 			for Card_Index in Card_Values loop
> 			TDeck (Index) := (Trump => False, Card_Value => Card_Index, Suit_Value => Suit_Index, others => Ada.Strings.Unbounded.Null_Unbounded_String);
> 			exit when Index=Maximum_Deck_Length; -- preventing CONSTRAINT_ERROR;
> 			Index:=Index+1;
> 			end loop;
> 			end loop;
> end Initialize;
> 
>    procedure Shuffle (TDeck : in out Deck) is
>       Position_Gen   : Card_Position_Random.Generator;
>       Temporary_Data : Card_Info;
>       Index_Random   : Card_Position;
>    begin
>       Card_Position_Random.Reset (Gen => Position_Gen);
>       for Index in Card_Position loop
>          Index_Random         := Card_Position_Random.Random (Gen => Position_Gen);
>          Temporary_Data       := TDeck (Index);
>          TDeck (Index)        := TDeck (Index_Random);
>          TDeck (Index_Random) := Temporary_Data;
>       end loop;
>    end Shuffle;
>    Tarot_Deck : Deck;
>    begin
>    Initialize(Tarot_Deck);
>    Shuffle(Tarot_Deck);
>    for Index in Card_Position loop -- just print the deck as shuffled
>    if Tarot_Deck(Index).Trump then
> 	Ada.Text_IO.Put_Line("Major Arcana/Trump: "&Trump_Values'Image(Tarot_Deck(Index).Trump_Value));
> else
> 	Ada.Text_IO.Put_Line("Minor Arcana: "&Card_Values'Image(Tarot_Deck(Index).Card_Value)&" of "&Card_Suits'Image(Tarot_Deck(Index).Suit_Value));
> 	end if;
> 	end loop;
>    end Tarot1;
> 
> Thanks for help.

The compiler does compile assignment of others => <> to uninitialized record components as Mr. Simon Wright noticed above, I have reproduced the bug both with GNAT 2017 GPL and FSF GNAT on Cygwin (6.4.0), problem is I don't have GNAT Pro subscription for access to AdaCore GNAT tracker, and I can't open an account on GCC Bugzilla either, as my mail to administration is rejected and direct account creation is disabled. We can only hope that powers that be take notice of this. Thanks for the suggestions by the way.


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

* Re: Array of records with default values not propagating to array
  2018-02-03 15:26   ` Simon Wright
  2018-02-03 16:07     ` Jere
@ 2018-02-04  9:21     ` Niklas Holsti
  2018-02-04  9:32       ` Simon Wright
  1 sibling, 1 reply; 13+ messages in thread
From: Niklas Holsti @ 2018-02-04  9:21 UTC (permalink / raw)


On 18-02-03 17:26 , Simon Wright wrote:

> I find that
>
>    type Card_Info (Trump : Boolean := False) is record
>       Name : Ada.Strings.Unbounded.Unbounded_String;
>       Divinatory_Meaning : Ada.Strings.Unbounded.Unbounded_String;
>       ...
>
>          TDeck (Index) :=
>            (Trump       => True,
>             Trump_Value => Index_1,
>             others      => <>);
>          ...
>
>             TDeck (Index) :=
>               (Trump      => False,
>                Card_Value => Card_Index,
>                Suit_Value => Suit_Index,
>                others     => <>);
>
> compiles OK and seems to run perfectly well. Presumably this is OK
> because the initial value for an otherwise-uninitialized unbounded
> string is the empty string. Or maybe it's GNAT being over-helpful, since
> it seems not to obey ARM 4.3.1(17.1)[1].
>
> [1] http://www.ada-auth.org/standards/rm12_w_tc1/html/RM-4-3-1.html#p17.1

I don't think that ARM paragraph applies to the "others" in this code. 
The paragraph says:

"A record_component_association for a discriminant without a 
default_expression shall have an expression rather than <>"

but the components covered by the "others" in this code are not 
discriminants. The discriminant is the Trump component, and the 
associations for Trump have an expression (True or False), not <>.

(Moreover, the Trump component has a default expression (False), which 
makes ARM 4.3.1(17.1) inapplicable even to "Trump => <>".)

-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
       .      @       .


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

* Re: Array of records with default values not propagating to array
  2018-02-04  9:21     ` Niklas Holsti
@ 2018-02-04  9:32       ` Simon Wright
  0 siblings, 0 replies; 13+ messages in thread
From: Simon Wright @ 2018-02-04  9:32 UTC (permalink / raw)


Niklas Holsti <niklas.holsti@tidorum.invalid> writes:

> On 18-02-03 17:26 , Simon Wright wrote:
>
>> I find that
>>
>>    type Card_Info (Trump : Boolean := False) is record
>>       Name : Ada.Strings.Unbounded.Unbounded_String;
>>       Divinatory_Meaning : Ada.Strings.Unbounded.Unbounded_String;
>>       ...
>>
>>          TDeck (Index) :=
>>            (Trump       => True,
>>             Trump_Value => Index_1,
>>             others      => <>);
>>          ...
>>
>>             TDeck (Index) :=
>>               (Trump      => False,
>>                Card_Value => Card_Index,
>>                Suit_Value => Suit_Index,
>>                others     => <>);
>>
>> compiles OK and seems to run perfectly well. Presumably this is OK
>> because the initial value for an otherwise-uninitialized unbounded
>> string is the empty string. Or maybe it's GNAT being over-helpful, since
>> it seems not to obey ARM 4.3.1(17.1)[1].
>>
>> [1] http://www.ada-auth.org/standards/rm12_w_tc1/html/RM-4-3-1.html#p17.1
>
> I don't think that ARM paragraph applies to the "others" in this
> code. The paragraph says:
>
> "A record_component_association for a discriminant without a
> default_expression shall have an expression rather than <>"
>
> but the components covered by the "others" in this code are not
> discriminants. The discriminant is the Trump component, and the
> associations for Trump have an expression (True or False), not <>.

Oh, yes.

I should have looked a bit further down: (19.1) says

   "... For a record_component_association with <>, if the
   component_declaration has a default_expression, that
   default_expression defines the value for the associated component(s);
   otherwise, the associated component(s) are initialized by default as
   for a stand-alone object of the component subtype (see 3.3.1)."

which is exactly what OP needs.


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

* Re: Array of records with default values not propagating to array
  2018-02-04  4:59 ` Bojan Bozovic
@ 2018-02-04  9:34   ` Simon Wright
  2018-02-04 10:07   ` Niklas Holsti
  1 sibling, 0 replies; 13+ messages in thread
From: Simon Wright @ 2018-02-04  9:34 UTC (permalink / raw)


Bojan Bozovic <bozovic.bojan@gmail.com> writes:

> The compiler does compile assignment of others => <> to uninitialized
> record components as Mr. Simon Wright noticed above, I have reproduced
> the bug both with GNAT 2017 GPL and FSF GNAT on Cygwin (6.4.0),
> problem is I don't have GNAT Pro subscription for access to AdaCore
> GNAT tracker, and I can't open an account on GCC Bugzilla either, as
> my mail to administration is rejected and direct account creation is
> disabled. We can only hope that powers that be take notice of
> this. Thanks for the suggestions by the way.

Actually this is not a bug, it's required behaviour as in
ARM4.3.1(19.1)[1].

[1]
http://www.ada-auth.org/standards/rm12_w_tc1/html/RM-4-3-1.html#p19.1


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

* Re: Array of records with default values not propagating to array
  2018-02-04  4:59 ` Bojan Bozovic
  2018-02-04  9:34   ` Simon Wright
@ 2018-02-04 10:07   ` Niklas Holsti
  2018-02-04 11:38     ` Bojan Bozovic
  1 sibling, 1 reply; 13+ messages in thread
From: Niklas Holsti @ 2018-02-04 10:07 UTC (permalink / raw)


On 18-02-04 06:59 , Bojan Bozovic wrote:
> On Saturday, February 3, 2018 at 12:06:52 PM UTC+1, Bojan Bozovic wrote:
>> When I defined a record, and set a default value for some of its
>> components, these don't propagate when I make array of these
>> records. Here is code that can be compiled, but I wonder do I
>> need to explicitly assign value for 'others' in 'Initialize'
>> procedure.

This is just a rule in Ada: in a record aggregate, one has to specify 
values for all the "needed components", whether or not the record type 
declaration supplies default values for some components.

This is different from a subprogram call, in which one can omit the 
parameter associations for parameters that have a default value.

The default values of record components are used in two cases: when one 
creates an object of the type, without giving an initial value, such as 
(in your code):

       Temporary_Data : Card_Info;

Here, the default values in the Card_Info declaration come into play, 
and define the initial values of those components of Temporary_Data.

Here it means that Temporary_Data.Trump is False, and Name and 
Divinatory_Meaning are null unbounded strings. The component 
Temporary_Data.Trump_Value has an undefined value, as it is not given 
any default value in the declaration of Card_Info.

However, in your code, defining explicit default values of 
Null_Unbounded_String for the components Name and Divinatory_Meaning is 
unnecessary, because every object of type Unbounded_String is 
initialised, by default, to Null_Unbounded_String.

The second case where default values of record components are used is in 
a record aggreggate where a component association says " ... => <>". 
Here, the "<>" means "use the default value, if there is one".

So, in your code, if a record aggregate for a Card_Info record says "... 
=> <>" for the components Name and Divinatory_Meaning, it means that 
these components will be given the value Null_Unbounded_String.

>> When I omit "others =>" in Initialize, I get compilation errors
>> at these lines both on FSF compiler and AdaCore GPL compiler on
>> Windows. Is this intended behavior or I am missing something?

It is intended behaviour. The relevant Reference Manual rule is 
http://www.ada-auth.org/standards/rm12_w_tc1/html/RM-4-3-1.html#p16 .

> The compiler does compile assignment of others => <> to uninitialized
> record components as Mr. Simon Wright noticed above,

Why do you believe that the components (Name and Divinatory_Meaning) are 
uninitialised? In my tests of the code, they are initialised, as 
expected, to Null_Unbounded_String.

> I have reproduced the bug both with GNAT 2017 GPL and FSF GNAT on
> Cygwin (6.4.0).

So far, I don't think there is any bug.

-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
       .      @       .

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

* Re: Array of records with default values not propagating to array
  2018-02-03 11:06 Array of records with default values not propagating to array Bojan Bozovic
                   ` (2 preceding siblings ...)
  2018-02-04  4:59 ` Bojan Bozovic
@ 2018-02-04 10:19 ` Jeffrey R. Carter
  3 siblings, 0 replies; 13+ messages in thread
From: Jeffrey R. Carter @ 2018-02-04 10:19 UTC (permalink / raw)


On 02/03/2018 12:06 PM, Bojan Bozovic wrote:
> When I defined a record, and set a default value for some of its components, these don't propagate when I make array of these records. Here is code that can be compiled, but I wonder do I need to explicitly assign value for 'others' in 'Initialize' procedure. This has nothing to do with Ada random number generation, I might have as well used Ada.Numerics.Float_Random, or the reusable code that was posted in another thread, with the same result, so I will post in this separate thread. When I omit "others =>" in Initialize, I get compilation errors at these lines both on FSF compiler and AdaCore GPL compiler on Windows. Is this intended behavior or I am missing something?

I'm not sure what you're experiencing. Your code, as given, compiles and works 
fine for me.

-- 
Jeff Carter
"I like it when the support group complains that they have
insufficient data on mean time to repair bugs in Ada software."
Robert I. Eachus
91


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

* Re: Array of records with default values not propagating to array
  2018-02-04 10:07   ` Niklas Holsti
@ 2018-02-04 11:38     ` Bojan Bozovic
  0 siblings, 0 replies; 13+ messages in thread
From: Bojan Bozovic @ 2018-02-04 11:38 UTC (permalink / raw)


On Sunday, February 4, 2018 at 11:07:10 AM UTC+1, Niklas Holsti wrote:
> On 18-02-04 06:59 , Bojan Bozovic wrote:
> > On Saturday, February 3, 2018 at 12:06:52 PM UTC+1, Bojan Bozovic wrote:
> >> When I defined a record, and set a default value for some of its
> >> components, these don't propagate when I make array of these
> >> records. Here is code that can be compiled, but I wonder do I
> >> need to explicitly assign value for 'others' in 'Initialize'
> >> procedure.
> 
> This is just a rule in Ada: in a record aggregate, one has to specify 
> values for all the "needed components", whether or not the record type 
> declaration supplies default values for some components.
> 
> This is different from a subprogram call, in which one can omit the 
> parameter associations for parameters that have a default value.
> 
> The default values of record components are used in two cases: when one 
> creates an object of the type, without giving an initial value, such as 
> (in your code):
> 
>        Temporary_Data : Card_Info;
> 
> Here, the default values in the Card_Info declaration come into play, 
> and define the initial values of those components of Temporary_Data.
> 
> Here it means that Temporary_Data.Trump is False, and Name and 
> Divinatory_Meaning are null unbounded strings. The component 
> Temporary_Data.Trump_Value has an undefined value, as it is not given 
> any default value in the declaration of Card_Info.
> 
> However, in your code, defining explicit default values of 
> Null_Unbounded_String for the components Name and Divinatory_Meaning is 
> unnecessary, because every object of type Unbounded_String is 
> initialised, by default, to Null_Unbounded_String.
> 
> The second case where default values of record components are used is in 
> a record aggreggate where a component association says " ... => <>". 
> Here, the "<>" means "use the default value, if there is one".
> 
> So, in your code, if a record aggregate for a Card_Info record says "... 
> => <>" for the components Name and Divinatory_Meaning, it means that 
> these components will be given the value Null_Unbounded_String.
> 
> >> When I omit "others =>" in Initialize, I get compilation errors
> >> at these lines both on FSF compiler and AdaCore GPL compiler on
> >> Windows. Is this intended behavior or I am missing something?
> 
> It is intended behaviour. The relevant Reference Manual rule is 
> http://www.ada-auth.org/standards/rm12_w_tc1/html/RM-4-3-1.html#p16 .
> 
> > The compiler does compile assignment of others => <> to uninitialized
> > record components as Mr. Simon Wright noticed above,
> 
> Why do you believe that the components (Name and Divinatory_Meaning) are 
> uninitialised? In my tests of the code, they are initialised, as 
> expected, to Null_Unbounded_String.
> 
> > I have reproduced the bug both with GNAT 2017 GPL and FSF GNAT on
> > Cygwin (6.4.0).
> 
> So far, I don't think there is any bug.
> 
> -- 
> Niklas Holsti
> Tidorum Ltd
> niklas holsti tidorum fi
>        .      @       .

When in record declaration making components uninitialized like:

Name : Ada.Strings.Unbounded.Unbounded_String;

I had made a mistake to believe these had no proper initialization and shouldn't have been assigned by others => <> in assignment during Initialize, but explicitly, as Simon Wright originally said. I don't know enough about the language itself to discern if something isn't implemented correctly by the compiler, but it is, as Simon Wright rectified his stance on this, so I just sent some spam to AdaCore about that, but I don't think it matters. ;)


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

end of thread, other threads:[~2018-02-04 11:38 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-02-03 11:06 Array of records with default values not propagating to array Bojan Bozovic
2018-02-03 14:16 ` Jere
2018-02-03 14:54   ` Bojan Bozovic
2018-02-03 15:26   ` Simon Wright
2018-02-03 16:07     ` Jere
2018-02-04  9:21     ` Niklas Holsti
2018-02-04  9:32       ` Simon Wright
2018-02-04  2:43 ` Robert Eachus
2018-02-04  4:59 ` Bojan Bozovic
2018-02-04  9:34   ` Simon Wright
2018-02-04 10:07   ` Niklas Holsti
2018-02-04 11:38     ` Bojan Bozovic
2018-02-04 10:19 ` Jeffrey R. Carter

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