comp.lang.ada
 help / color / mirror / Atom feed
* derived formal types and known discriminants
@ 2017-06-23  0:45 sbelmont700
  2017-06-23 17:26 ` Randy Brukardt
  2017-07-03 17:24 ` Jere
  0 siblings, 2 replies; 14+ messages in thread
From: sbelmont700 @ 2017-06-23  0:45 UTC (permalink / raw)


Can any language lawyer explain the reasoning behind precluding known discriminants for general formal derived types?  For example, I can write this:

generic
  type T is new P with private; -- constrained (i.e. none)
  
and I can write this:

generic
  type T (<>) is new P with private;  -- unconstrained (i.e. any)
  
But I can't write

generic
  type T (foo : Integer) is new P with private;  -- (just one integer)
  
presumably because 12.5.1~11/3 says "The declaration of a formal derived type shall not have a known_discriminant_part", to wit GNAT complains "discriminants not allowed for this formal type".  It would seems as though if unknown discriminants are legal, known would be an easier subset, and my interest has been piqued to the reason why.

Thank you for any insight

-sb


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

* Re: derived formal types and known discriminants
  2017-06-23  0:45 derived formal types and known discriminants sbelmont700
@ 2017-06-23 17:26 ` Randy Brukardt
  2017-06-29 14:15   ` sbelmont700
  2017-07-03 17:24 ` Jere
  1 sibling, 1 reply; 14+ messages in thread
From: Randy Brukardt @ 2017-06-23 17:26 UTC (permalink / raw)


<sbelmont700@gmail.com> wrote in message 
news:a9316065-923c-439e-9176-8f3eb469c601@googlegroups.com...
>Can any language lawyer explain the reasoning behind precluding known 
>discriminants
>for general formal derived types?

I don't know, I can only guess. And my guess would be that discriminants 
that are added/removed would be a problem. Within the generic, you could 
declare objects giving those discriminant values, but they might not be 
right. For a type with unknown discriminants, you can't declare an object at 
all, so that's easier.

But why using the same matching rules used for formal private types wouldn't 
work, I don't know. Or maybe it just didn't seem worth worrying about, given 
that formal derived types are mainly useful to give Steve Baird a rare 
mechanism for the amazing semantic issues that he comes up with. (Yes, 
formal tagged derived types have some uses in deep type hierarchies, and 
that's about it, because no one declares other kinds of derived types in the 
first place.)

                                      Randy.


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

* Re: derived formal types and known discriminants
  2017-06-23 17:26 ` Randy Brukardt
@ 2017-06-29 14:15   ` sbelmont700
  2017-06-29 14:39     ` Dmitry A. Kazakov
  2017-06-30  1:10     ` Randy Brukardt
  0 siblings, 2 replies; 14+ messages in thread
From: sbelmont700 @ 2017-06-29 14:15 UTC (permalink / raw)


On Friday, June 23, 2017 at 1:26:12 PM UTC-4, Randy Brukardt wrote:
>
> I don't know, I can only guess. And my guess would be that discriminants 
> that are added/removed would be a problem. Within the generic, you could 
> declare objects giving those discriminant values, but they might not be 
> right. For a type with unknown discriminants, you can't declare an object at 
> all, so that's easier.
> 
> But why using the same matching rules used for formal private types wouldn't 
> work, I don't know. Or maybe it just didn't seem worth worrying about, given 
> that formal derived types are mainly useful to give Steve Baird a rare 
> mechanism for the amazing semantic issues that he comes up with. (Yes, 
> formal tagged derived types have some uses in deep type hierarchies, and 
> that's about it, because no one declares other kinds of derived types in the 
> first place.)
> 
>                                       Randy.


You imply that the feature is little-used, but isn't this (one of) the primary mechanisms for MI via the so-called "mixin"?  In Mr. Taft's paper from 1994 ("Multiple Inheritance in Ada 9X"), he lists the three common cases, of which #2 is the "generic with a formal derived type" method, i.e. instead of having C extend both A and B, you make one of the parents a generic that extends a formal derived type of the other, and than have the child and extend that.  But if I understand it (quite likely not the case...), this effectively limits this method to parent types without discriminants?

For example, suppose I have the abstract type A with some arbitrary discriminants, and I extend it into two concrete types Ax and Ay; each has the option to either inherit the parents discriminants outright, or replace them with their own set (constraining the parent as needed).  Now suppose I wish to extend Ax and Ay into Bx and By, respectively, but also extend them from an unrelated abstract type W with it's own arbitrary discriminants.  I arrange W into a generic package with a formal type derived from A, with the intent of instantiating it twice (once on Ax and once on Ay), and then extending each of those to create Bx and By, thus giving me everything from A and W together.

But now I appear to be stuck, since there's no way to give W discriminants; doing so requires constraining the discriminants of the formal type, which I have no visibility into, since they are unknown.  Consequently, I just have to inherit the parents discriminants as-is, and none of the functionality of W can depend on them.  If, however, there was the ability to have a known_formal_part on the formal derived type, I could at least do this in situations where the actuals (Ax and Ay) had consistent numbers/types of discriminants, e.g. "T is a type extended from A with one Integer discriminant 'D'", and so W could extend T by constraining D.

Am I understanding all this correctly? Or are there perhaps other ways of doing this I am overlooking?  I admittedly just starting to delve into Ada's whole 'mix-in' approach, so please set me straight if i'm trying to put a round peg into a square hole.

Thank you again for your responses.

-sb


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

* Re: derived formal types and known discriminants
  2017-06-29 14:15   ` sbelmont700
@ 2017-06-29 14:39     ` Dmitry A. Kazakov
  2017-06-29 17:40       ` Robert Eachus
  2017-06-30  1:10     ` Randy Brukardt
  1 sibling, 1 reply; 14+ messages in thread
From: Dmitry A. Kazakov @ 2017-06-29 14:39 UTC (permalink / raw)


On 29/06/2017 16:15, sbelmont700@gmail.com wrote:

> You imply that the feature is little-used, but isn't this (one of)
> the primary mechanisms for MI via the so-called "mixin"?  In Mr.
> Taft's paper from 1994 ("Multiple Inheritance in Ada 9X"), he lists
> the three common cases, of which #2 is the "generic with a formal
> derived type" method, i.e. instead of having C extend both A and B,
> you make one of the parents a generic that extends a formal derived
> type of the other, and than have the child and extend that.
Speaking from my sad experience it creates such a mess no real-life 
project can allow. I guess other people either tried it like me or were 
wise enough not to.

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

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

* Re: derived formal types and known discriminants
  2017-06-29 14:39     ` Dmitry A. Kazakov
@ 2017-06-29 17:40       ` Robert Eachus
  0 siblings, 0 replies; 14+ messages in thread
From: Robert Eachus @ 2017-06-29 17:40 UTC (permalink / raw)


On Thursday, June 29, 2017 at 10:39:47 AM UTC-4, Dmitry A. Kazakov wrote:
> On 29/06/2017 16:15, sbelmont700@gmail.com wrote:
> 
> > You imply that the feature is little-used, but isn't this (one of)
> > the primary mechanisms for MI via the so-called "mixin"?  In Mr.
> > Taft's paper from 1994 ("Multiple Inheritance in Ada 9X"), he lists
> > the three common cases, of which #2 is the "generic with a formal
> > derived type" method, i.e. instead of having C extend both A and B,
> > you make one of the parents a generic that extends a formal derived
> > type of the other, and than have the child and extend that.
> Speaking from my sad experience it creates such a mess no real-life 
> project can allow. I guess other people either tried it like me or were 
> wise enough not to.

I've done it, it works, but to make it manageable/maintainable takes a bit of discipline.  The actual project was a mailbox system so that distributed programs could send (and receive) messages without having to worry about the actual system support.  (In particular whether programs shared memory, or messages required copying bytes.)

The base type Message had no discriminants.  This could be extended by mix-ins with discriminants to allow arrays and records to be passed.  You could use multiple mixins, but if two content types both needed discriminants, the best solution was to wrap them a record type and use a mixin for that.

Worked fine.  Last I heard someone was trying to extend it to allow passing data between programs running in virtual memory on the same hardware without extra copying.  (I'm not expressing that well.  A memory pool shared between the programs.  It seemed much easier to me to run all the programs in the same virtual space to begin with.  But it was not my project...)


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

* Re: derived formal types and known discriminants
  2017-06-29 14:15   ` sbelmont700
  2017-06-29 14:39     ` Dmitry A. Kazakov
@ 2017-06-30  1:10     ` Randy Brukardt
  2017-06-30  7:24       ` Dmitry A. Kazakov
  1 sibling, 1 reply; 14+ messages in thread
From: Randy Brukardt @ 2017-06-30  1:10 UTC (permalink / raw)


<sbelmont700@gmail.com> wrote in message 
news:82a59ee9-8d55-4c73-9daf-e9f7d9ab8a8f@googlegroups.com...
On Friday, June 23, 2017 at 1:26:12 PM UTC-4, Randy Brukardt wrote:
...
>You imply that the feature is little-used, but isn't this (one of) the
> primary mechanisms for MI via the so-called "mixin"?

Ada 2005 got interfaces for proper interface inheritance. Mix-ins don't get 
used much in new code.

In any case, tagged formal derived types was the case I was referring to 
when I said "Yes, formal tagged derived types have some uses in deep type 
hierarchies, and that's about it, because no one declares other kinds of 
derived types in the first place." They're the only useful type of formal 
derived types, but the majority of the compilication comes from the other 
kinds.

...
>But if I understand it (quite likely not the case...), this effectively 
>limits
>this method to parent types without discriminants?

Surely, but no real loss. Using discriminants with tagged types is pretty 
rare in itself. So is useful multiple inheritance. That makes the 
probability of needing both very small.

My recollection is that Ada 95 didn't even allow discriminants on tagged 
types at various points in its development, because of the raft of semantic 
problems that occur. Those eventually were solved by getting rid of the 
possibility of changing the discriminants.

Personally, I find that discriminants are only useful if they are mutable 
(that is, can be changed via assignment), and as noted above, tagged 
discriminants are never mutable. Non-mutable discriminants are inflexible 
and usually just get in the way (arrays have a similar problem with their 
bounds). YMMV.

                                    Randy.




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

* Re: derived formal types and known discriminants
  2017-06-30  1:10     ` Randy Brukardt
@ 2017-06-30  7:24       ` Dmitry A. Kazakov
  2017-06-30 18:09         ` Randy Brukardt
  0 siblings, 1 reply; 14+ messages in thread
From: Dmitry A. Kazakov @ 2017-06-30  7:24 UTC (permalink / raw)


On 30/06/2017 03:10, Randy Brukardt wrote:

> Surely, but no real loss. Using discriminants with tagged types is pretty
> rare in itself.

Access discriminants are needed to work around lack of constructors and 
full multiple inheritance. That is when one object refers to its 
separate part via an access discriminant.

Value discriminants are needed for having components of unconstrained types.

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


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

* Re: derived formal types and known discriminants
  2017-06-30  7:24       ` Dmitry A. Kazakov
@ 2017-06-30 18:09         ` Randy Brukardt
  2017-07-04  0:30           ` sbelmont700
  0 siblings, 1 reply; 14+ messages in thread
From: Randy Brukardt @ 2017-06-30 18:09 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:oj4ubr$190j$1@gioia.aioe.org...
> On 30/06/2017 03:10, Randy Brukardt wrote:
>
>> Surely, but no real loss. Using discriminants with tagged types is pretty
>> rare in itself.
>
> Access discriminants are needed to work around lack of constructors and 
> full multiple inheritance. That is when one object refers to its separate 
> part via an access discriminant.

Possibly, but that seems hard to work with. And as someone that rarely sees 
the value of inheritance in the first place, I doubt I would bother trying. 
YMMV.

> Value discriminants are needed for having components of unconstrained 
> types.

Sure, but they're very inflexible in that usage (as bad or worse than the 
original unconstrained types). So I tend to view these as an either/or 
proposition: untagged, mutable types with discriminants, or tagged types 
without discriminants. Again, YMMV.

                   Randy.



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

* Re: derived formal types and known discriminants
  2017-06-23  0:45 derived formal types and known discriminants sbelmont700
  2017-06-23 17:26 ` Randy Brukardt
@ 2017-07-03 17:24 ` Jere
  1 sibling, 0 replies; 14+ messages in thread
From: Jere @ 2017-07-03 17:24 UTC (permalink / raw)


On Thursday, June 22, 2017 at 8:45:22 PM UTC-4, sbelm...@gmail.com wrote:
> Can any language lawyer explain the reasoning behind precluding known discriminants for general formal derived types?  For example, I can write this:
> 
> generic
>   type T is new P with private; -- constrained (i.e. none)
>   
> and I can write this:
> 
> generic
>   type T (<>) is new P with private;  -- unconstrained (i.e. any)
>   
> But I can't write
> 
> generic
>   type T (foo : Integer) is new P with private;  -- (just one integer)
>   
> presumably because 12.5.1~11/3 says "The declaration of a formal derived type shall not have a known_discriminant_part", to wit GNAT complains "discriminants not allowed for this formal type".  It would seems as though if unknown discriminants are legal, known would be an easier subset, and my interest has been piqued to the reason why.
> 
> Thank you for any insight
> 
> -sb

I've often wondered this myself.  The best I came up with was to use an intermediate type:

type NP(Foo : Integer) is new P with null record;

and then do the generic like this:

generic
   type T is new NP with private;
package G is
   subtype Test_Type is T;
end G;

A bit more cumbersome, but that's how I managed it.


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

* Re: derived formal types and known discriminants
  2017-06-30 18:09         ` Randy Brukardt
@ 2017-07-04  0:30           ` sbelmont700
  2017-07-04  1:36             ` gautier_niouzes
                               ` (2 more replies)
  0 siblings, 3 replies; 14+ messages in thread
From: sbelmont700 @ 2017-07-04  0:30 UTC (permalink / raw)


On Friday, June 30, 2017 at 2:10:01 PM UTC-4, Randy Brukardt wrote:
> 
> Sure, but they're very inflexible in that usage (as bad or worse than the 
> original unconstrained types). So I tend to view these as an either/or 
> proposition: untagged, mutable types with discriminants, or tagged types 
> without discriminants. Again, YMMV.
> 


At the risk of having some of the other thread's shade thrown in here, aren't tagged discriminated records the de facto way of doing initialization?  That is, extending a Controlled type and then using discriminants in place of ctor arguments?  I can see that a "real" discriminated record (i.e. variant records) probably have little use in a tagged hierarchy, but access discriminants (et al) seem much closer to 'constant record elements' than a truly discriminated record.

After all, how else is one supposed to do construction for an abstract parent type?  In C++, for example, an abstract type still has a constructor (that all children would have to explicitly call with the required arguments), but in Ada 'constructing functions' are off the table since the type is abstract.  So apparently the only thing left is to use Initialize and then ferry any required arguments over as discriminants?  This is the method given in many texts and examples, so please set me straight if i'm way off base.

Thank you again to everyone for the helpful comments and continued support.

-sb


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

* Re: derived formal types and known discriminants
  2017-07-04  0:30           ` sbelmont700
@ 2017-07-04  1:36             ` gautier_niouzes
  2017-07-04  2:29             ` Randy Brukardt
  2017-07-04  7:09             ` Dmitry A. Kazakov
  2 siblings, 0 replies; 14+ messages in thread
From: gautier_niouzes @ 2017-07-04  1:36 UTC (permalink / raw)


"construction for an abstract parent type": just a wild guess: you would perhaps do something like this:

  type T is abstract tagged record
    i: Integer:= 1;
  end record;

  procedure Reset (x: in out T) is
    fresh_new: T;   --  GNAT: type of object cannot be abstract
  begin
    x:= fresh_new;  --  GNAT: target of assignment operation must not be abstract
  end;

...and you are blocked at the lines with comments.
Then a solution is a non-abstract grand-parent type:

  type Pre_T is tagged record
    i: Integer:= 1;
  end record;

  type T is abstract new Pre_T with null record;

  procedure Reset (x: in out T) is
    fresh_new: Pre_T;
  begin
    Pre_T(x):= fresh_new;
  end;

HTH...
_____________________________________________________________
A free online game in Ada: http://pasta.phyrama.com/game.html

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

* Re: derived formal types and known discriminants
  2017-07-04  0:30           ` sbelmont700
  2017-07-04  1:36             ` gautier_niouzes
@ 2017-07-04  2:29             ` Randy Brukardt
  2017-07-04  7:09             ` Dmitry A. Kazakov
  2 siblings, 0 replies; 14+ messages in thread
From: Randy Brukardt @ 2017-07-04  2:29 UTC (permalink / raw)


<sbelmont700@gmail.com> wrote in message 
news:a1bd4695-00ff-49a8-a07a-84ebdb043202@googlegroups.com...
On Friday, June 30, 2017 at 2:10:01 PM UTC-4, Randy Brukardt wrote:
>> Sure, but they're very inflexible in that usage (as bad or worse than the
>> original unconstrained types). So I tend to view these as an either/or
>> proposition: untagged, mutable types with discriminants, or tagged types
>> without discriminants. Again, YMMV.

>At the risk of having some of the other thread's shade thrown in here, 
>aren't
>tagged discriminated records the de facto way of doing initialization? 
>That is,
>extending a Controlled type and then using discriminants in place of ctor 
>arguments?

I've heard of people trying to use that sort of thing, but I find it too 
inflexible (in that you have to declare an object at exactly the right 
place). Thus most of my types default-initialize to an "invalid" state, and 
there is one or more "Create" or "Open" routines to make a usable version. A 
bit more complicated, but it allows the initialization to occur anywhere 
(not necessarily where the object is declared, which usually is picked to 
give the proper lifetime for the object - that is, the destruction point) 
and the initialization can have arbitrary parameters.

You do need a check (or precondition) for validity for most operations, but 
that should be optimizable (if written as a precondition with an appropriate 
stable property [in Ada 202x]). So it shouldn't cost much if anything at 
runtime.

This after all is the model of file objects in Ada 83, and it works well for 
them and many other things.

                                             Randy.


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

* Re: derived formal types and known discriminants
  2017-07-04  0:30           ` sbelmont700
  2017-07-04  1:36             ` gautier_niouzes
  2017-07-04  2:29             ` Randy Brukardt
@ 2017-07-04  7:09             ` Dmitry A. Kazakov
  2017-07-04 17:34               ` Shark8
  2 siblings, 1 reply; 14+ messages in thread
From: Dmitry A. Kazakov @ 2017-07-04  7:09 UTC (permalink / raw)


On 04/07/2017 02:30, sbelmont700@gmail.com wrote:

> At the risk of having some of the other thread's shade thrown in
> here, aren't tagged discriminated records the de facto way of doing
> initialization?  That is, extending a Controlled type and then using
> discriminants in place of ctor arguments?
Sure. I am using this quite frequently. Sometimes I go this way:

    type Factory_Type is record ...;
    type Actual_Type (Parameters : not null access Factory_Type) is
      tagged ...;

There are obvious limitations to that. Especially that you have to keep 
parameters after object construction. Of course one can also do this:

    type Factory_Type is record ...;
    type Factory_Type_Ptr is access Factory_Type'Class;
    type Actual_Type (Parameters : Factory_Type_Ptr) is
      new Limited_Controlled ...;

Then in the Initialize you call Unchecked_Deallocate on Parameters and 
comment with an appropriate number of exclamation marks that objects 
must be created this way:

    X : Actual_Type (new Parameter'(...));

Isn't getting rid of such constructs a valid argument to have proper 
constructors?

BTW, if discriminants were abstracted as they should have been, that 
would be the way to implement constructors with parameters. You could 
declare a parameter as a public discriminant non-existing in the actual 
implementation and the type user would have to supply it when declaring 
an object.

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

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

* Re: derived formal types and known discriminants
  2017-07-04  7:09             ` Dmitry A. Kazakov
@ 2017-07-04 17:34               ` Shark8
  0 siblings, 0 replies; 14+ messages in thread
From: Shark8 @ 2017-07-04 17:34 UTC (permalink / raw)


On Tuesday, July 4, 2017 at 1:09:57 AM UTC-6, Dmitry A. Kazakov wrote:
> 
> BTW, if discriminants were abstracted as they should have been, that 
> would be the way to implement constructors with parameters. You could 
> declare a parameter as a public discriminant non-existing in the actual 
> implementation and the type user would have to supply it when declaring 
> an object.

Hm, that is an interesting idea.


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

end of thread, other threads:[~2017-07-04 17:34 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-06-23  0:45 derived formal types and known discriminants sbelmont700
2017-06-23 17:26 ` Randy Brukardt
2017-06-29 14:15   ` sbelmont700
2017-06-29 14:39     ` Dmitry A. Kazakov
2017-06-29 17:40       ` Robert Eachus
2017-06-30  1:10     ` Randy Brukardt
2017-06-30  7:24       ` Dmitry A. Kazakov
2017-06-30 18:09         ` Randy Brukardt
2017-07-04  0:30           ` sbelmont700
2017-07-04  1:36             ` gautier_niouzes
2017-07-04  2:29             ` Randy Brukardt
2017-07-04  7:09             ` Dmitry A. Kazakov
2017-07-04 17:34               ` Shark8
2017-07-03 17:24 ` Jere

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