comp.lang.ada
 help / color / mirror / Atom feed
* Can't access record attribute in derived type
@ 2017-03-08 14:15 Mart van de Wege
  2017-03-08 14:24 ` G.B.
                   ` (2 more replies)
  0 siblings, 3 replies; 13+ messages in thread
From: Mart van de Wege @ 2017-03-08 14:15 UTC (permalink / raw)


Hi,

I have the following definitions

private
type Creature is new Base_Creature with record
      Attributes	 : Attribute_Array;
      Gender             : Possible_Gender := Unknown;
      Current_Hit_Points : Integer;
      Parents            : Group_Of_Creatures.List;
      --  An instance of Ada.Containers.Indefinite_Doubly_Linked_Lists
end record;

In child package #1 (Persons):

private
   type Person is new Creature with record
   [...]
and in child package #2 (Knights):
   type Knight is new Person with record
   [...]

I try to read the first element of the Parents attribute in knights.adb
like this:

   function Father (K : in Knight) return Knight is
   begin
      return K.Parents.First_Element;
   end Father;

And the compiler complains:

 "no selector "Parents" for type "Knight" defined"

What am I missing here? The declarations are private, but shouldn't a
tagged type inherit the entire record of its parent type? That means
that it should have a Parents selector, shouldn't it?

Mart

-- 
"We will need a longer wall when the revolution comes."
    --- AJS, quoting an uncertain source.


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

* Re: Can't access record attribute in derived type
  2017-03-08 14:15 Can't access record attribute in derived type Mart van de Wege
@ 2017-03-08 14:24 ` G.B.
  2017-03-08 15:06   ` Mart van de Wege
  2017-03-08 20:08 ` Randy Brukardt
  2017-03-08 21:03 ` Shark8
  2 siblings, 1 reply; 13+ messages in thread
From: G.B. @ 2017-03-08 14:24 UTC (permalink / raw)


On 08/03/2017 15:15, Mart van de Wege wrote:
> The declarations are private, but shouldn't a
> tagged type inherit the entire record of its parent type? That means
> that it should have a Parents selector, shouldn't it?

Just to make sure, is this also a hierarchy of child
packages, like

P
   Creature
P.C
   Person
P.C.G
   Knight

so that every derived type's definition has visibility
into the respective parent package's private part?


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

* Re: Can't access record attribute in derived type
  2017-03-08 14:24 ` G.B.
@ 2017-03-08 15:06   ` Mart van de Wege
  2017-03-08 19:30     ` Niklas Holsti
  0 siblings, 1 reply; 13+ messages in thread
From: Mart van de Wege @ 2017-03-08 15:06 UTC (permalink / raw)


"G.B." <bauhaus@notmyhomepage.invalid> writes:

> On 08/03/2017 15:15, Mart van de Wege wrote:
>> The declarations are private, but shouldn't a
>> tagged type inherit the entire record of its parent type? That means
>> that it should have a Parents selector, shouldn't it?
>
> Just to make sure, is this also a hierarchy of child
> packages, like
>
> P
>   Creature
> P.C
>   Person
> P.C.G
>   Knight
>
> so that every derived type's definition has visibility
> into the respective parent package's private part?
>
Yep, it is.

Mart
-- 
"We will need a longer wall when the revolution comes."
    --- AJS, quoting an uncertain source.


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

* Re: Can't access record attribute in derived type
  2017-03-08 15:06   ` Mart van de Wege
@ 2017-03-08 19:30     ` Niklas Holsti
  2017-03-08 21:05       ` Mart van de Wege
  0 siblings, 1 reply; 13+ messages in thread
From: Niklas Holsti @ 2017-03-08 19:30 UTC (permalink / raw)


On 17-03-08 17:06 , Mart van de Wege wrote:
> "G.B." <bauhaus@notmyhomepage.invalid> writes:
>
>> On 08/03/2017 15:15, Mart van de Wege wrote:
>>> The declarations are private, but shouldn't a
>>> tagged type inherit the entire record of its parent type? That means
>>> that it should have a Parents selector, shouldn't it?
>>
>> Just to make sure, is this also a hierarchy of child
>> packages, like
>>
>> P
>>   Creature
>> P.C
>>   Person
>> P.C.G
>>   Knight
>>
>> so that every derived type's definition has visibility
>> into the respective parent package's private part?
>>
> Yep, it is.

But you said that the problem appeared in a file called "knights.adb". 
If that is the full name, and if you are using the GNAT file-name 
convention, it is _not_ a child package of any other package. Did you 
abbreviate the file name in your post?

A child package like Creatures.Persons.Knights would have a file-name of 
the form "creatures-persons-knights.adb".

What are the actual and full names of all the relevant packages?

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


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

* Re: Can't access record attribute in derived type
  2017-03-08 14:15 Can't access record attribute in derived type Mart van de Wege
  2017-03-08 14:24 ` G.B.
@ 2017-03-08 20:08 ` Randy Brukardt
  2017-03-08 21:06   ` Mart van de Wege
  2017-03-08 21:12   ` Mart van de Wege
  2017-03-08 21:03 ` Shark8
  2 siblings, 2 replies; 13+ messages in thread
From: Randy Brukardt @ 2017-03-08 20:08 UTC (permalink / raw)



"Mart van de Wege" <mvdwege@gmail.com> wrote in message 
news:86mvcv4zyu.fsf@gaheris.avalon.lan...
> Hi,
>
> I have the following definitions
>
> private
> type Creature is new Base_Creature with record
>      Attributes : Attribute_Array;
>      Gender             : Possible_Gender := Unknown;
>      Current_Hit_Points : Integer;
>      Parents            : Group_Of_Creatures.List;
>      --  An instance of Ada.Containers.Indefinite_Doubly_Linked_Lists
> end record;
>
> In child package #1 (Persons):
>
> private
>   type Person is new Creature with record
>   [...]
> and in child package #2 (Knights):
>   type Knight is new Person with record
>   [...]
>
> I try to read the first element of the Parents attribute in knights.adb
> like this:
>
>   function Father (K : in Knight) return Knight is
>   begin
>      return K.Parents.First_Element;
>   end Father;
>
> And the compiler complains:
>
> "no selector "Parents" for type "Knight" defined"
>
> What am I missing here? The declarations are private, but shouldn't a
> tagged type inherit the entire record of its parent type? That means
> that it should have a Parents selector, shouldn't it?

I suspect we'll need to see a more complete example to definitively say what 
the problem is.

But if I had to guess, I'd suggest that you've run afoul of the "sibling 
inheritance problem". The rule for visibility for child components is that 
*all* of components of the *all* of the ancestors have to be visible at the 
point of declaration of the child type. If even one of the ancestors is not 
visible (as happens when deriving from a type defined in a sibling child 
package), then the components aren't visible, either.

Note that in such a case, if you have visiblity on some but not all of the 
ancestors, you can type convert the object to make them visible. In your 
example above:

     return Creature(K).Parents.First_Element;

will work if you have some intermediate ancestor without visible components. 
So, if the above works, you have a sibling inheritance problem, and your 
choices are either to use conversions like the above, or move the types so 
that all of the ancestors are visible.

                                     Randy.



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

* Re: Can't access record attribute in derived type
  2017-03-08 14:15 Can't access record attribute in derived type Mart van de Wege
  2017-03-08 14:24 ` G.B.
  2017-03-08 20:08 ` Randy Brukardt
@ 2017-03-08 21:03 ` Shark8
  2017-03-08 21:16   ` Mart van de Wege
  2 siblings, 1 reply; 13+ messages in thread
From: Shark8 @ 2017-03-08 21:03 UTC (permalink / raw)


On Wednesday, March 8, 2017 at 7:15:22 AM UTC-7, Mart van de Wege wrote:
> Hi,
> 
> I have the following definitions
> 
> private
> type Creature is new Base_Creature with record
>       Attributes	 : Attribute_Array;
>       Gender             : Possible_Gender := Unknown;
>       Current_Hit_Points : Integer;
>       Parents            : Group_Of_Creatures.List;
>       --  An instance of Ada.Containers.Indefinite_Doubly_Linked_Lists
> end record;
> 
> In child package #1 (Persons):
> 
> private
>    type Person is new Creature with record
>    [...]
> and in child package #2 (Knights):
>    type Knight is new Person with record
>    [...]
> 
> I try to read the first element of the Parents attribute in knights.adb
> like this:
> 
>    function Father (K : in Knight) return Knight is
>    begin
>       return K.Parents.First_Element;
>    end Father;

One Problem is that K.Parents.First_Element *isn't* of type Knight -- It's of type Creature -- that is surely one problem.

Secondly, the construct 
> type Creature is new Base_Creature with record
>       Attributes	 : Attribute_Array;
>       Gender             : Possible_Gender := Unknown;
>       Current_Hit_Points : Integer;
>       Parents            : Group_Of_Creatures.List;
>       --  An instance of Ada.Containers.Indefinite_Doubly_Linked_Lists
> end record;
cannot exist, as you cannot instantiate the Container without completing the type which can't be complete without the instantiation of the Container (because of the Parents element).

I would recommend something like this:

    Type Base_Creature is abstract tagged record
       Attributes         : Attribute_Array;
       Gender             : Possible_Gender := Unknown;
       Current_Hit_Points : Integer;
    end record;

--...
    Package Creature_Grouping is new Ada.Containers.Indefinite_Doubly_Linked_Lists( Base_Creature'Class );
--...

    Type Creature is new Base_Creature with record
       Parents : Creature_Grouping.List;
    end record;

--...
    Type Person is new Creature with --[...]
    Function Father( Input : Person ) return Creature'Class is
      ( Input.Parents.First_Element );
--...
    Type Knight is new Person with --[...]

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

* Re: Can't access record attribute in derived type
  2017-03-08 19:30     ` Niklas Holsti
@ 2017-03-08 21:05       ` Mart van de Wege
  0 siblings, 0 replies; 13+ messages in thread
From: Mart van de Wege @ 2017-03-08 21:05 UTC (permalink / raw)


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

> On 17-03-08 17:06 , Mart van de Wege wrote:
>> "G.B." <bauhaus@notmyhomepage.invalid> writes:
>>
>>> On 08/03/2017 15:15, Mart van de Wege wrote:
>>>> The declarations are private, but shouldn't a
>>>> tagged type inherit the entire record of its parent type? That means
>>>> that it should have a Parents selector, shouldn't it?
>>>
>>> Just to make sure, is this also a hierarchy of child
>>> packages, like
>>>
>>> P
>>>   Creature
>>> P.C
>>>   Person
>>> P.C.G
>>>   Knight
>>>
>>> so that every derived type's definition has visibility
>>> into the respective parent package's private part?
>>>
>> Yep, it is.
>
> But you said that the problem appeared in a file called
> "knights.adb". If that is the full name, and if you are using the GNAT
> file-name convention, it is _not_ a child package of any other
> package. Did you abbreviate the file name in your post?
>
> A child package like Creatures.Persons.Knights would have a file-name
> of the form "creatures-persons-knights.adb".
>
> What are the actual and full names of all the relevant packages?

Aaah. I think I see the problem. Yes, Knights is on the same level of
the hierarchy as Persons.

The full hierarchy is:

Pendragon
Pendragon.Persons
Pendragon.Knights

Knights withs Persons, but they are on the same level.

(And for the curious, this is a random character generator for the King
Arthur Pendragon roleplaying game. It works quite well for the 50% of
the rules I already covered, creating single characters, but I have
problems getting my design to work with families, aka containers within
the Persons/Knights objects containing other Persons/Knights).

Mart

-- 
"We will need a longer wall when the revolution comes."
    --- AJS, quoting an uncertain source.

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

* Re: Can't access record attribute in derived type
  2017-03-08 20:08 ` Randy Brukardt
@ 2017-03-08 21:06   ` Mart van de Wege
  2017-03-08 21:12   ` Mart van de Wege
  1 sibling, 0 replies; 13+ messages in thread
From: Mart van de Wege @ 2017-03-08 21:06 UTC (permalink / raw)


"Randy Brukardt" <randy@rrsoftware.com> writes:

> I suspect we'll need to see a more complete example to definitively say what 
> the problem is.
>
> But if I had to guess, I'd suggest that you've run afoul of the "sibling 
> inheritance problem". The rule for visibility for child components is that 
> *all* of components of the *all* of the ancestors have to be visible at the 
> point of declaration of the child type. If even one of the ancestors is not 
> visible (as happens when deriving from a type defined in a sibling child 
> package), then the components aren't visible, either.
>
> Note that in such a case, if you have visiblity on some but not all of the 
> ancestors, you can type convert the object to make them visible. In your 
> example above:
>
>      return Creature(K).Parents.First_Element;
>
> will work if you have some intermediate ancestor without visible components. 
> So, if the above works, you have a sibling inheritance problem, and your 
> choices are either to use conversions like the above, or move the types so 
> that all of the ancestors are visible.
>
>                                      Randy.
>
>
>

-- 
"We will need a longer wall when the revolution comes."
    --- AJS, quoting an uncertain source.


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

* Re: Can't access record attribute in derived type
  2017-03-08 20:08 ` Randy Brukardt
  2017-03-08 21:06   ` Mart van de Wege
@ 2017-03-08 21:12   ` Mart van de Wege
  2017-03-08 21:25     ` Mart van de Wege
  1 sibling, 1 reply; 13+ messages in thread
From: Mart van de Wege @ 2017-03-08 21:12 UTC (permalink / raw)


"Randy Brukardt" <randy@rrsoftware.com> writes:

> I suspect we'll need to see a more complete example to definitively say what 
> the problem is.
>
The full code lives at https://github.com/mvdwege/pendragon

Note that some stuff is in incomplete branches, and I still have some
locally committed changes that are not in the github repo. The code that
was throwing errors among them.

> But if I had to guess, I'd suggest that you've run afoul of the "sibling 
> inheritance problem". The rule for visibility for child components is that 
> *all* of components of the *all* of the ancestors have to be visible at the 
> point of declaration of the child type. If even one of the ancestors is not 
> visible (as happens when deriving from a type defined in a sibling child 
> package), then the components aren't visible, either.
>
It appears that that is it. While Knights is a descendant of Person, the
Knights package is indeed a sibling of Persons, not a child.

I failed to let my package design keep up with the actual design of the
objects.

The problem went away when I moved the Knights definition into the
Persons package. Now I know why.

(In fact, my original design had a wild growth of child packages which I
was in the process of pruning back as being excessively complex. Which
probably caused my confusion above).

> Note that in such a case, if you have visiblity on some but not all of the 
> ancestors, you can type convert the object to make them visible. In your 
> example above:
>
>      return Creature(K).Parents.First_Element;

Yes, using conversions in my unit tests suppressed other errors I
couldn't get, and now I understand why those conversions were
necessary.

Mart

-- 
"We will need a longer wall when the revolution comes."
    --- AJS, quoting an uncertain source.


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

* Re: Can't access record attribute in derived type
  2017-03-08 21:03 ` Shark8
@ 2017-03-08 21:16   ` Mart van de Wege
  0 siblings, 0 replies; 13+ messages in thread
From: Mart van de Wege @ 2017-03-08 21:16 UTC (permalink / raw)


Shark8 <onewingedshark@gmail.com> writes:

> On Wednesday, March 8, 2017 at 7:15:22 AM UTC-7, Mart van de Wege wrote:
>> Hi,
>> 
>> I have the following definitions
>> 
>> private
>> type Creature is new Base_Creature with record
>>       Attributes	 : Attribute_Array;
>>       Gender             : Possible_Gender := Unknown;
>>       Current_Hit_Points : Integer;
>>       Parents            : Group_Of_Creatures.List;
>>       --  An instance of Ada.Containers.Indefinite_Doubly_Linked_Lists
>> end record;
>> 
>> In child package #1 (Persons):
>> 
>> private
>>    type Person is new Creature with record
>>    [...]
>> and in child package #2 (Knights):
>>    type Knight is new Person with record
>>    [...]
>> 
>> I try to read the first element of the Parents attribute in knights.adb
>> like this:
>> 
>>    function Father (K : in Knight) return Knight is
>>    begin
>>       return K.Parents.First_Element;
>>    end Father;
>
> One Problem is that K.Parents.First_Element *isn't* of type Knight --
> It's of type Creature -- that is surely one problem.
>
Yeah, that is solved by some explicit conversions. I am not happy with
that, but this is still the first phase of my attempt at implementing
families, and getting my head around the intricacies of OO in Ada.

> Secondly, the construct 
>> type Creature is new Base_Creature with record
>>       Attributes	 : Attribute_Array;
>>       Gender             : Possible_Gender := Unknown;
>>       Current_Hit_Points : Integer;
>>       Parents            : Group_Of_Creatures.List;
>>       --  An instance of Ada.Containers.Indefinite_Doubly_Linked_Lists
>> end record;
> cannot exist, as you cannot instantiate the Container without completing the type which can't be complete without the instantiation of the Container (because of the Parents element).
>
> I would recommend something like this:
>
>     Type Base_Creature is abstract tagged record
>        Attributes         : Attribute_Array;
>        Gender             : Possible_Gender := Unknown;
>        Current_Hit_Points : Integer;
>     end record;
>
> --...
>     Package Creature_Grouping is new Ada.Containers.Indefinite_Doubly_Linked_Lists( Base_Creature'Class );
> --...
That's more or less what I did. Creature is derived from abstract
Base_Creature, and Group_Of_Creatures is defined as new
Ada.Containers.Indefinite_Doubly_Linked_list (Element_Type =>
Base_Creature'Class).

Mart

-- 
"We will need a longer wall when the revolution comes."
    --- AJS, quoting an uncertain source.


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

* Re: Can't access record attribute in derived type
  2017-03-08 21:12   ` Mart van de Wege
@ 2017-03-08 21:25     ` Mart van de Wege
  2017-03-08 21:50       ` Simon Wright
  0 siblings, 1 reply; 13+ messages in thread
From: Mart van de Wege @ 2017-03-08 21:25 UTC (permalink / raw)


Mart van de Wege <mvdwege@gmail.com> writes:

> "Randy Brukardt" <randy@rrsoftware.com> writes:
>
>> I suspect we'll need to see a more complete example to definitively say what 
>> the problem is.
>>
> The full code lives at https://github.com/mvdwege/pendragon
>
> Note that some stuff is in incomplete branches, and I still have some
> locally committed changes that are not in the github repo. The code that
> was throwing errors among them.

Screw that. Based on my reading of the answers, I am going to delete the
persons and family_and_relatives branches and sit down and do a decent
design first.

Mart

-- 
"We will need a longer wall when the revolution comes."
    --- AJS, quoting an uncertain source.


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

* Re: Can't access record attribute in derived type
  2017-03-08 21:25     ` Mart van de Wege
@ 2017-03-08 21:50       ` Simon Wright
  2017-03-08 22:35         ` Mart van de Wege
  0 siblings, 1 reply; 13+ messages in thread
From: Simon Wright @ 2017-03-08 21:50 UTC (permalink / raw)


Mart van de Wege <mvdwege@gmail.com> writes:

> Mart van de Wege <mvdwege@gmail.com> writes:
>
>> "Randy Brukardt" <randy@rrsoftware.com> writes:
>>
>>> I suspect we'll need to see a more complete example to definitively
>>> say what the problem is.
>>>
>> The full code lives at https://github.com/mvdwege/pendragon
>>
>> Note that some stuff is in incomplete branches, and I still have some
>> locally committed changes that are not in the github repo. The code
>> that was throwing errors among them.
>
> Screw that. Based on my reading of the answers, I am going to delete
> the persons and family_and_relatives branches and sit down and do a
> decent design first.

I suspect most of us have reached this stage in a project at some point
in our careers! You will feel better afterwards ...

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

* Re: Can't access record attribute in derived type
  2017-03-08 21:50       ` Simon Wright
@ 2017-03-08 22:35         ` Mart van de Wege
  0 siblings, 0 replies; 13+ messages in thread
From: Mart van de Wege @ 2017-03-08 22:35 UTC (permalink / raw)


Simon Wright <simon@pushface.org> writes:

> Mart van de Wege <mvdwege@gmail.com> writes:
>
>> Mart van de Wege <mvdwege@gmail.com> writes:
>>
>>> "Randy Brukardt" <randy@rrsoftware.com> writes:
>>>
>>>> I suspect we'll need to see a more complete example to definitively
>>>> say what the problem is.
>>>>
>>> The full code lives at https://github.com/mvdwege/pendragon
>>>
>>> Note that some stuff is in incomplete branches, and I still have some
>>> locally committed changes that are not in the github repo. The code
>>> that was throwing errors among them.
>>
>> Screw that. Based on my reading of the answers, I am going to delete
>> the persons and family_and_relatives branches and sit down and do a
>> decent design first.
>
> I suspect most of us have reached this stage in a project at some point
> in our careers! You will feel better afterwards ...

I've been working on this off and on for almost a year now, and I have
reached that point several times ;)

And you're right, I've felt better every time I did that. In fact, just
after reading the comments I coded up an implementation that correctly
assigns a Father to a Person'Class object, stuffs it in the Parents
list, and reads it correctly. So the first steps of the redesign
work. Now I'm going to think on how to implement the entire family tree
according to the rules.

The nice thing about implementing RPG rulesets is that the ruleset
itself presents a decent first attempt at a spec ;)

Mart

-- 
"We will need a longer wall when the revolution comes."
    --- AJS, quoting an uncertain source.

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

end of thread, other threads:[~2017-03-08 22:35 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-03-08 14:15 Can't access record attribute in derived type Mart van de Wege
2017-03-08 14:24 ` G.B.
2017-03-08 15:06   ` Mart van de Wege
2017-03-08 19:30     ` Niklas Holsti
2017-03-08 21:05       ` Mart van de Wege
2017-03-08 20:08 ` Randy Brukardt
2017-03-08 21:06   ` Mart van de Wege
2017-03-08 21:12   ` Mart van de Wege
2017-03-08 21:25     ` Mart van de Wege
2017-03-08 21:50       ` Simon Wright
2017-03-08 22:35         ` Mart van de Wege
2017-03-08 21:03 ` Shark8
2017-03-08 21:16   ` Mart van de Wege

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