comp.lang.ada
 help / color / mirror / Atom feed
* generics and records
@ 2005-02-27 19:34 spambox
  2005-02-27 20:16 ` Dmitry A. Kazakov
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: spambox @ 2005-02-27 19:34 UTC (permalink / raw)


Hello,
in the process of learning Ada, I came to the problem of generics and
records. I want to instantiate a package with a record type:

generic
 type x is private;
package ...
private
 type xx is new x;
end ...

When I want to use it:

type myrecord is
 ...
package somename is new seeabove(myrecord);

I don't know if this is the correct way. The problem is, how do I make
a component of myrecord available to the package?

Thanks,

andrej




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

* Re: generics and records
  2005-02-27 19:34 generics and records spambox
@ 2005-02-27 20:16 ` Dmitry A. Kazakov
  2005-02-27 21:31   ` spambox
  2005-02-28  6:02 ` Jeffrey Carter
  2005-03-01 11:21 ` Martin Krischik
  2 siblings, 1 reply; 10+ messages in thread
From: Dmitry A. Kazakov @ 2005-02-27 20:16 UTC (permalink / raw)


On 27 Feb 2005 11:34:00 -0800, spambox@volja.net wrote:

> in the process of learning Ada, I came to the problem of generics and
> records. I want to instantiate a package with a record type:
> 
> generic
>  type x is private;
> package ...
> private
>  type xx is new x;
> end ...
> 
> When I want to use it:
> 
> type myrecord is
>  ...
> package somename is new seeabove(myrecord);
> 
> I don't know if this is the correct way. The problem is, how do I make
> a component of myrecord available to the package?

A generic package knows as much about its actual parameters as the formal
parameters tell. If the formal parameter is nothing more than just "is
private" then it is all what the package may know, i.e. almost nothing.

If the components of the actual parameter need to be known in the package,
then that has to be reflected in by the formal parameters. For example:

1. Getter / setter used to access the components

generic
   type Record_Type is private;
   type Value_Type is private;
   function Get_A (Object : Record_Type) return Value_Type is <>;
   procedure Set_A (Object : in out Record_Type; A : Value_Type) is <>;
package Foo is
   ...

Instantiation:

type My_Record is
   A : Float;
end record;
function Get_A (Object : My_Record) return Float;
procedure Set_A (Object : in out My_Record; A : Float);
package My_Foo is new Foo (My_Record, Float);

2. Inheritance from a record type with known components:

type Common_Base is tagged record
   A : Float; -- This will be visible in Foo
end record;

generic
   type Record_Type is new Common_Base with private;
package Foo is
   ...

Instantiation:

type My_Record is new Common_Base with record
   ... -- These new components will be inaccessible in Foo!
end record;
package My_Foo is new Foo (My_Record);

3. Mixing of 1 and 2. The common base is abstract and has no components.
Instead of that it defines the interface (getter and setter) to access the
components.

type Common_Base is abstract tagged null record;
function Get_A (Object : Common_Base) return Float is abstract;
procedure Set_A (Object : in out Common_Base; A : Float) is abstract;

Here Common_Base defines the interface of a record type with Get_A and
Set_A.

generic
   type Record_Type is new Common_Base with private;
package Foo is
   ...

Instantiation:

type My_Record is new Common_Base with
   A : Float;
end record;
function Get_A (Object : My_Record) return Float; -- Override
procedure Set_A (Object : in out My_Record; A : Float);
package My_Foo is new Foo (My_Record);

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



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

* Re: generics and records
  2005-02-27 20:16 ` Dmitry A. Kazakov
@ 2005-02-27 21:31   ` spambox
  2005-02-28  8:47     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 10+ messages in thread
From: spambox @ 2005-02-27 21:31 UTC (permalink / raw)


Dmitry A. Kazakov wrote:

> 2. Inheritance from a record type with known components:
>
> type Common_Base is tagged record
>    A : Float; -- This will be visible in Foo
> end record;
>
> generic
>    type Record_Type is new Common_Base with private;
> package Foo is
>    ...
>
> Instantiation:
>
> type My_Record is new Common_Base with record
>    ... -- These new components will be inaccessible in Foo!
> end record;
> package My_Foo is new Foo (My_Record);

Thanks for the prompt response. One more question: how do I make the
components (the whole record?) known? Where must it be declared?

andrej




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

* Re: generics and records
  2005-02-27 19:34 generics and records spambox
  2005-02-27 20:16 ` Dmitry A. Kazakov
@ 2005-02-28  6:02 ` Jeffrey Carter
  2005-03-01 11:21 ` Martin Krischik
  2 siblings, 0 replies; 10+ messages in thread
From: Jeffrey Carter @ 2005-02-28  6:02 UTC (permalink / raw)


spambox@volja.net wrote:

> in the process of learning Ada, I came to the problem of generics and
> records. I want to instantiate a package with a record type:
> 
> generic
>  type x is private;
> package ...
> private
>  type xx is new x;
> end ...
> 
> When I want to use it:
> 
> type myrecord is
>  ...
> package somename is new seeabove(myrecord);
> 
> I don't know if this is the correct way. The problem is, how do I make
> a component of myrecord available to the package?

The formal part of a generic specifies what the generic needs in order 
to provide its services to its clients. If the generic needs to know 
about the specific components of a specific record type, then it is 
probably too tightly bound to the concept of that record type for it to 
be a formal parameter of the generic.

-- 
Jeff Carter
"Have you gone berserk? Can't you see that that man is a ni?"
Blazing Saddles
38



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

* Re: generics and records
  2005-02-27 21:31   ` spambox
@ 2005-02-28  8:47     ` Dmitry A. Kazakov
  2005-02-28  9:00       ` spambox
  0 siblings, 1 reply; 10+ messages in thread
From: Dmitry A. Kazakov @ 2005-02-28  8:47 UTC (permalink / raw)


On 27 Feb 2005 13:31:05 -0800, spambox@volja.net wrote:

> Dmitry A. Kazakov wrote:
> 
>> 2. Inheritance from a record type with known components:
>>
>> type Common_Base is tagged record
>>    A : Float; -- This will be visible in Foo
>> end record;
>>
>> generic
>>    type Record_Type is new Common_Base with private;
>> package Foo is
>>    ...
>>
>> Instantiation:
>>
>> type My_Record is new Common_Base with record
>>    ... -- These new components will be inaccessible in Foo!
>> end record;
>> package My_Foo is new Foo (My_Record);
> 
> Thanks for the prompt response. One more question: how do I make the
> components (the whole record?) known? Where must it be declared?

You can't do that. Ada has a contract model of generics. That means that
Foo in the example above will never directly see the whole record, only its
Common_Base part. The primitive operations defined on Common_Base will. So
if Foo has to access all record, the only way to do it is to express what
Foo should do in terms of primitive operations defined on Common_Base. They
can dispatch to the specific operations defined on the actual type.
Usually, it is sufficient for all purposes and also is a good OO-ish
programming style. But there is no way to write a generic unit working with
whatever components of an actual parameter. Ada does not provide abstract
record interfaces with enumeration of components and their types at run
time. Though you can implement something close to that using map container
types instead of record types. Probably this is what you actually need. But
again, to work through primitive operations is better.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



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

* Re: generics and records
  2005-02-28  8:47     ` Dmitry A. Kazakov
@ 2005-02-28  9:00       ` spambox
  2005-02-28 10:07         ` Dmitry A. Kazakov
  0 siblings, 1 reply; 10+ messages in thread
From: spambox @ 2005-02-28  9:00 UTC (permalink / raw)



Dmitry A. Kazakov wrote:
> >> 2. Inheritance from a record type with known components:
> >>
> >> type Common_Base is tagged record
> >>    A : Float; -- This will be visible in Foo
> >> end record;
> >>
> >> generic
> >>    type Record_Type is new Common_Base with private;
> >> package Foo is
> >>    ...
> >>
> >> Instantiation:
> >>
> >> type My_Record is new Common_Base with record
> >>    ... -- These new components will be inaccessible in Foo!
> >> end record;
> >> package My_Foo is new Foo (My_Record);

> You can't do that. Ada has a contract model of generics. That means
that
> Foo in the example above will never directly see the whole record,
only its
> Common_Base part. The primitive operations defined on Common_Base
will. So
> if Foo has to access all record, the only way to do it is to express
what
> Foo should do in terms of primitive operations defined on
Common_Base. They
> can dispatch to the specific operations defined on the actual type.
> Usually, it is sufficient for all purposes and also is a good OO-ish
> programming style. But there is no way to write a generic unit
working with
> whatever components of an actual parameter. Ada does not provide
abstract
> record interfaces with enumeration of components and their types at
run
> time. Though you can implement something close to that using map
container
> types instead of record types. Probably this is what you actually
need. But
> again, to work through primitive operations is better.

Yes, I understand. I was too eager to try your solution out, failed and
phrased my question poorly. I'm perfectly content with a record like
Common_Base above. But where should its definition be put? It can't go
into the package specs, where the "generic ..." part belongs. But if
it's not there, how can it be seen? -- "type Record_Type is new
Common_Base with private;" 
andrej




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

* Re: generics and records
  2005-02-28  9:00       ` spambox
@ 2005-02-28 10:07         ` Dmitry A. Kazakov
  0 siblings, 0 replies; 10+ messages in thread
From: Dmitry A. Kazakov @ 2005-02-28 10:07 UTC (permalink / raw)


On 28 Feb 2005 01:00:59 -0800, spambox@volja.net wrote:

> Dmitry A. Kazakov wrote:
>>>> 2. Inheritance from a record type with known components:
>>>>
>>>> type Common_Base is tagged record
>>>>    A : Float; -- This will be visible in Foo
>>>> end record;
>>>>
>>>> generic
>>>>    type Record_Type is new Common_Base with private;
>>>> package Foo is
>>>>    ...
>>>>
>>>> Instantiation:
>>>>
>>>> type My_Record is new Common_Base with record
>>>>    ... -- These new components will be inaccessible in Foo!
>>>> end record;
>>>> package My_Foo is new Foo (My_Record);
> 
>> You can't do that. Ada has a contract model of generics. That means that
>> Foo in the example above will never directly see the whole record, only its
>> Common_Base part. The primitive operations defined on Common_Base will. So
>> if Foo has to access all record, the only way to do it is to express what
>> Foo should do in terms of primitive operations defined on Common_Base. They
>> can dispatch to the specific operations defined on the actual type.
>> Usually, it is sufficient for all purposes and also is a good OO-ish
>> programming style. But there is no way to write a generic unit working with
>> whatever components of an actual parameter. Ada does not provide abstract
>> record interfaces with enumeration of components and their types at run
>> time. Though you can implement something close to that using map container
>> types instead of record types. Probably this is what you actually need. But
>> again, to work through primitive operations is better.
> 
> Yes, I understand. I was too eager to try your solution out, failed and
> phrased my question poorly. I'm perfectly content with a record like
> Common_Base above. But where should its definition be put? It can't go
> into the package specs, where the "generic ..." part belongs. But if
> it's not there, how can it be seen? -- "type Record_Type is new
> Common_Base with private;" 
> andrej

You can:

1. put Common_Base in another package and "with/use" that package in the
generic package specification.

package Bar is
   type Common_Base is ...;
end Bar;
----------------------
with Bar; use Bar;
generic
   type Record_Type is new Common_Base with private;
package Foo is
   ...
end Foo;

2. put both Common_Base and Foo in one package:

package Bar is
   type Common_Base is ...;
   generic
      type Record_Type is new Common_Base with private;
   package Foo is
      ...
   end Foo;
end Bar;

3. put Common_Base in the parent package of Foo:

package Bar is
   type Common_Base is ...;
end Bar;
--------------------
generic
   type Record_Type is new Common_Base with private;
package Bar.Foo is
   ...
end Bar.Foo;

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



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

* Re: generics and records
  2005-02-27 19:34 generics and records spambox
  2005-02-27 20:16 ` Dmitry A. Kazakov
  2005-02-28  6:02 ` Jeffrey Carter
@ 2005-03-01 11:21 ` Martin Krischik
  2005-03-01 19:47   ` Georg Bauhaus
  2 siblings, 1 reply; 10+ messages in thread
From: Martin Krischik @ 2005-03-01 11:21 UTC (permalink / raw)


spambox@volja.net wrote:

> Hello,
> in the process of learning Ada, I came to the problem of generics and
> records. I want to instantiate a package with a record type:
> 
> generic
>  type x is private;

You need a common ancestor class for this construct to work:

type x is new y with private;

> package ...
> private
>  type xx is new x;
> end ...

Martin

-- 
mailto://krischik@users.sourceforge.net
Ada programming at: http://ada.krischik.com




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

* Re: generics and records
  2005-03-01 11:21 ` Martin Krischik
@ 2005-03-01 19:47   ` Georg Bauhaus
  2005-03-01 20:17     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 10+ messages in thread
From: Georg Bauhaus @ 2005-03-01 19:47 UTC (permalink / raw)


Martin Krischik wrote:

>>generic
>> type x is private;
> 
> 
> You need a common ancestor class for this construct to work:
> 
> type x is new y with private;
> 
> 
>>package ...
>>private
>> type xx is new x;
>>end ...

Yes and no. The actual parameter is not a record in
the following example (Natural), but it could be one.

procedure P is

   generic
      type X is private;
   package G is
      type Y is new X;

      -- disallow multiplication and division in type Y

      function "*"(a, b: Y) return Y is abstract;
      function "/"(a, b: Y) return Y is abstract;
   end G;


   package I is new G(Natural);

   use I;

   v: Y := 1;

begin
   v := v + 1;
end P;



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

* Re: generics and records
  2005-03-01 19:47   ` Georg Bauhaus
@ 2005-03-01 20:17     ` Dmitry A. Kazakov
  0 siblings, 0 replies; 10+ messages in thread
From: Dmitry A. Kazakov @ 2005-03-01 20:17 UTC (permalink / raw)


On Tue, 01 Mar 2005 20:47:24 +0100, Georg Bauhaus wrote:

> Martin Krischik wrote:
> 
>>>generic
>>> type x is private;
>> 
>> You need a common ancestor class for this construct to work:
>> 
>> type x is new y with private;
>> 
>> 
>>>package ...
>>>private
>>> type xx is new x;
>>>end ...
> 
> Yes and no.

Rather no than yes. The following is illegal:

generic
   type X is new Baz with private;
package Foo is
   type XX is new X;
end Foo;

For whatever sad reasons but type cloning using "type X is new Y;" is not
allowed for publicly tagged types.

Personally I would prefer

   subtype X is Y with Z;

to present

   type X is new Y with Z;

and treat the latter rather as:

   type X is new Y with Z;
= subtype <anonymous> is Y with Z;
   type X is new <anonymous>;

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



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

end of thread, other threads:[~2005-03-01 20:17 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-02-27 19:34 generics and records spambox
2005-02-27 20:16 ` Dmitry A. Kazakov
2005-02-27 21:31   ` spambox
2005-02-28  8:47     ` Dmitry A. Kazakov
2005-02-28  9:00       ` spambox
2005-02-28 10:07         ` Dmitry A. Kazakov
2005-02-28  6:02 ` Jeffrey Carter
2005-03-01 11:21 ` Martin Krischik
2005-03-01 19:47   ` Georg Bauhaus
2005-03-01 20:17     ` Dmitry A. Kazakov

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