comp.lang.ada
 help / color / mirror / Atom feed
* Full view of a private partial view cannot be a subtype
@ 2017-12-03  2:14 Jere
  2017-12-03 12:01 ` Jeffrey R. Carter
                   ` (2 more replies)
  0 siblings, 3 replies; 46+ messages in thread
From: Jere @ 2017-12-03  2:14 UTC (permalink / raw)


Say I have some type:

   package Base is
      type Instance is tagged limited private;
      procedure Operation(Object : in out Instance);
   private
      type Instance is tagged limited null record;
      procedure Operation(Object : in out Instance) is null;
   end Base;

It might have 20 or so operations, but this is a simplified
example.  There are times where in another package I want to
subtype Base.Instance and do renames of the operations in order
to bring them all into scope (or whatever the correct term is):

   package New_Type1 is
      subtype Instance is Base.Instance;
      procedure Operation(Object : in out Instance);
      
   private
      
      procedure Operation(Object : in out Instance) renames Base.Operation;
   end New_Type1;

(NOTE:  is there a better way to do this?)

This is all well and good, but sometimes while I as an implementer
want this kind of relationship, I don't necessarily want to expose
that relationship outside the private section of a package.  Here I 
run into a problem as I cannot (as far as I can tell) do:

   package New_Type2 is
      type Instance is tagged limited private;
      procedure Operation(Object : in out Instance);
   private
      subtype Instance is Base.Instance;
      procedure Operation(Object : in out Instance renames Base.Operation;
   end New_Type2;

as it fails with an error ("Instance" not type conformant with declaration)
on the subtype line.

Instead I have to do (again, unless there is a better way):

   package New_Type2 is
      type Instance is tagged limited private;
      procedure Operation(Object : in out Instance);
      
   private
      type Instance is new Base.Instance with null record;
   end New_Type2;
   
   package body New_Type2 is
      procedure Operation(Object : in out Instance) is
      begin
         Base.Instance(Object).Operation;
      end Operation;
   end New_Type2;

This might be ok, but it's a lot of noise added (I now
need a body for all of my operations and need to type
convert parameters and any return values).  I'm also not
sure the semantics between the method I wanted and the
method I had to use are the same (in all situations).  I.E.
I don't know if 

   procedure Operation(Object : in out Instance renames Base.Operation;

has the same semantics as

   procedure Operation(Object : in out Instance) is
   begin
      Base.Instance(Object).Operation;
   end Operation;

My instinct says they do not.  That may be ok, but I am 
just unsure.  

So I guess my question is two part:

1.  Is there a way to make the full view of a private type
    a subtype when the partial view is not a subtype? Or am
    I forced to derive a new type?

2.  If it isn't possible, are there any language reasons for
    why that must be so?  Would making a full view of a type
    actually a subtype under the hood break something?
   


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

* Re: Full view of a private partial view cannot be a subtype
  2017-12-03  2:14 Full view of a private partial view cannot be a subtype Jere
@ 2017-12-03 12:01 ` Jeffrey R. Carter
  2017-12-03 13:33   ` Jere
  2017-12-04 20:49 ` Randy Brukardt
  2017-12-18 20:45 ` Stephen Leake
  2 siblings, 1 reply; 46+ messages in thread
From: Jeffrey R. Carter @ 2017-12-03 12:01 UTC (permalink / raw)


On 12/03/2017 03:14 AM, Jere wrote:
> 
>     package New_Type1 is
>        subtype Instance is Base.Instance;
>        procedure Operation(Object : in out Instance);
>     private
>        procedure Operation(Object : in out Instance) renames Base.Operation;

You can make the renaming visible as well. There doesn't seem to be any reason 
to hide the fact that Operation is a renaming of Base.Operation.

> I'm also not
> sure the semantics between the method I wanted and the
> method I had to use are the same (in all situations).

No, with a direct renaming, a call to the renaming is the same as a call to the 
original procedure. With a wrapper around the call to the original procedure, 
you have 2 calls. If you inline the wrapper then they should be equivalent.

> 1.  Is there a way to make the full view of a private type
>      a subtype when the partial view is not a subtype? Or am
>      I forced to derive a new type?

You cannot use a subtype to complete a private type. But you're not forced to 
use a derived type and convert all over the place. Another option is

private
    type T is [tagged] [limited] record
       V : Base.T;
    end record;

and then refer to Object.V with no conversions.

If your private type doesn't need to be tagged, you can also do

private
    type T is array (1 .. 1) of Base.T;

and then refer to Object (1), again with no conversions. Given that the bounds 
are static and you're always going to use a static index, I'd expect the 
indexing to be optimized away.

-- 
Jeff Carter
"So if I understand 'The Matrix Reloaded' correctly, the Matrix is
basically a Microsoft operating system--it runs for a while and
then crashes and reboots. By design, no less. Neo is just a
memory leak that's too hard to fix, so they left him in ... The
users don't complain because they're packed in slush and kept
sedated."
Marin D. Condic
65


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

* Re: Full view of a private partial view cannot be a subtype
  2017-12-03 12:01 ` Jeffrey R. Carter
@ 2017-12-03 13:33   ` Jere
  2017-12-03 14:34     ` Jeffrey R. Carter
  0 siblings, 1 reply; 46+ messages in thread
From: Jere @ 2017-12-03 13:33 UTC (permalink / raw)


On Sunday, December 3, 2017 at 7:01:50 AM UTC-5, Jeffrey R. Carter wrote:
> On 12/03/2017 03:14 AM, Jere wrote:
> > 
> >     package New_Type1 is
> >        subtype Instance is Base.Instance;
> >        procedure Operation(Object : in out Instance);
> >     private
> >        procedure Operation(Object : in out Instance) renames Base.Operation;
> 
> You can make the renaming visible as well. There doesn't seem to be any reason 
> to hide the fact that Operation is a renaming of Base.Operation.

Yes.  Sorry about that.  In my haste to covert what I had to a reduced example
I forgot to make it null in the visible part.  I would normally only hide that
for private types.

> 
> > I'm also not
> > sure the semantics between the method I wanted and the
> > method I had to use are the same (in all situations).
> 
> No, with a direct renaming, a call to the renaming is the same as a call to the 
> original procedure. With a wrapper around the call to the original procedure, 
> you have 2 calls. If you inline the wrapper then they should be equivalent.

I thought I remembered reading in the RM somewhere that if a renaming was a
completion, that it was equivalent to a wrapper, but to be honest my memory
isn't great.  And even if I remembered correctly, I may not have understood
the context of that fully.


> 
> > 1.  Is there a way to make the full view of a private type
> >      a subtype when the partial view is not a subtype? Or am
> >      I forced to derive a new type?
> 
> You cannot use a subtype to complete a private type. But you're not forced to 
> use a derived type and convert all over the place. Another option is
> 
> private
>     type T is [tagged] [limited] record
>        V : Base.T;
>     end record;
> 
> and then refer to Object.V with no conversions.
> 
Thanks!  I didn't even think about nesting it like that.  That'll work.

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

* Re: Full view of a private partial view cannot be a subtype
  2017-12-03 13:33   ` Jere
@ 2017-12-03 14:34     ` Jeffrey R. Carter
  2017-12-03 17:44       ` Robert Eachus
  2017-12-03 22:23       ` Jere
  0 siblings, 2 replies; 46+ messages in thread
From: Jeffrey R. Carter @ 2017-12-03 14:34 UTC (permalink / raw)


On 12/03/2017 02:33 PM, Jere wrote:
> 
> I thought I remembered reading in the RM somewhere that if a renaming was a
> completion, that it was equivalent to a wrapper, but to be honest my memory
> isn't great.  And even if I remembered correctly, I may not have understood
> the context of that fully.

You're thinking of ARM 8.5.4 (7.1/1), which does say that. However, "equivalent" 
means that it gives the same results, not that it has to be implemented as such. 
If your renaming-as-body is in the pkg spec, it would be a pretty poor compiler 
that didn't implement a call to it the same as a call to a renaming-as-declaration.

> Thanks!  I didn't even think about nesting it like that.  That'll work.

Many people seem to think that as much as possible should be done through type 
extension. They act as though the only tool they have is the hammer of type 
extension, and so view every problem as a nail. In my experience type extension 
is usually best avoided whenever possible.

-- 
Jeff Carter
"So if I understand 'The Matrix Reloaded' correctly, the Matrix is
basically a Microsoft operating system--it runs for a while and
then crashes and reboots. By design, no less. Neo is just a
memory leak that's too hard to fix, so they left him in ... The
users don't complain because they're packed in slush and kept
sedated."
Marin D. Condic
65

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

* Re: Full view of a private partial view cannot be a subtype
  2017-12-03 14:34     ` Jeffrey R. Carter
@ 2017-12-03 17:44       ` Robert Eachus
  2017-12-03 18:50         ` Simon Wright
  2017-12-03 19:03         ` Jeffrey R. Carter
  2017-12-03 22:23       ` Jere
  1 sibling, 2 replies; 46+ messages in thread
From: Robert Eachus @ 2017-12-03 17:44 UTC (permalink / raw)


On Sunday, December 3, 2017 at 9:34:51 AM UTC-5, Jeffrey R. Carter wrote:
 
> Many people seem to think that as much as possible should be done through type 
> extension. They act as though the only tool they have is the hammer of type 
> extension, and so view every problem as a nail. In my experience type extension 
> is usually best avoided whenever possible.

Several decades ago, there was a fun paper: "Nesting in Ada is for the birds." by Lori Clarke et. al. https://dl.acm.org/citation.cfm?id=948651  It may be time for a similar article about type extension.  But it can't have quite so catchy a title.  Building a type using mix-ins works nicely, but you want all the actual objects in the program to be of the (many) great grandchild type.  I'll have to do more thinking about it.


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

* Re: Full view of a private partial view cannot be a subtype
  2017-12-03 17:44       ` Robert Eachus
@ 2017-12-03 18:50         ` Simon Wright
  2017-12-03 22:10           ` Robert Eachus
  2017-12-03 19:03         ` Jeffrey R. Carter
  1 sibling, 1 reply; 46+ messages in thread
From: Simon Wright @ 2017-12-03 18:50 UTC (permalink / raw)


Robert Eachus <rieachus@comcast.net> writes:

> Several decades ago, there was a fun paper: "Nesting in Ada is for the
> birds." by Lori Clarke
> et. al. https://dl.acm.org/citation.cfm?id=948651

Interesting! My own (subconscious) guidelines mean nesting is almost
absent; for a start, most subprograms are fairly small.

It always worries me when a nested subprogram makes uplevel references
to its parent's variables.

I imagine that most of us would regard a main program all of whose
called subprograms were nested inside it (recursively) with horror.

That said, completely forbidding declare blocks is going a step too far!


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

* Re: Full view of a private partial view cannot be a subtype
  2017-12-03 17:44       ` Robert Eachus
  2017-12-03 18:50         ` Simon Wright
@ 2017-12-03 19:03         ` Jeffrey R. Carter
  1 sibling, 0 replies; 46+ messages in thread
From: Jeffrey R. Carter @ 2017-12-03 19:03 UTC (permalink / raw)


On 12/03/2017 06:44 PM, Robert Eachus wrote:
> 
> Several decades ago, there was a fun paper: "Nesting in Ada is for the birds." by Lori Clarke et. al. https://dl.acm.org/citation.cfm?id=948651  It may be time for a similar article about type extension.  But it can't have quite so catchy a title.  Building a type using mix-ins works nicely, but you want all the actual objects in the program to be of the (many) great grandchild type.  I'll have to do more thinking about it.

In 1994 there was a paper titled "Ada's Design Goals and Object-Oriented 
Programming" in /Ada Letters/. Not quite as many decades ago, and probably not 
as fun, and definitely not as catchy a title.

-- 
Jeff Carter
"So if I understand 'The Matrix Reloaded' correctly, the Matrix is
basically a Microsoft operating system--it runs for a while and
then crashes and reboots. By design, no less. Neo is just a
memory leak that's too hard to fix, so they left him in ... The
users don't complain because they're packed in slush and kept
sedated."
Marin D. Condic
65


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

* Re: Full view of a private partial view cannot be a subtype
  2017-12-03 18:50         ` Simon Wright
@ 2017-12-03 22:10           ` Robert Eachus
  0 siblings, 0 replies; 46+ messages in thread
From: Robert Eachus @ 2017-12-03 22:10 UTC (permalink / raw)


On Sunday, December 3, 2017 at 1:50:44 PM UTC-5, Simon Wright wrote:
 
> That said, completely forbidding declare blocks is going a step too far!

Definitely. I tend to think of the structure of a main program is initialization code, and a declare block for the initializations that have to wait for a file to be read.  For example, a file with a large matrix preceded by its dimensions.  You can't tell how many tasks you need or where to split the file until you see the dimensions.  Opening the file in a library package just seems wrong somehow.

Also nonce procedures and functions to provide operations on a locally declared type are not really nesting anyway. My rule used to be that if the compiler was going to inline it, no worries.  (Today's compilers are getting a bit too good at inlining. ;-)


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

* Re: Full view of a private partial view cannot be a subtype
  2017-12-03 14:34     ` Jeffrey R. Carter
  2017-12-03 17:44       ` Robert Eachus
@ 2017-12-03 22:23       ` Jere
  2017-12-04  8:25         ` Dmitry A. Kazakov
  2017-12-04 18:04         ` Jeffrey R. Carter
  1 sibling, 2 replies; 46+ messages in thread
From: Jere @ 2017-12-03 22:23 UTC (permalink / raw)


On Sunday, December 3, 2017 at 9:34:51 AM UTC-5, Jeffrey R. Carter wrote:
> On 12/03/2017 02:33 PM, Jere wrote:
> > Thanks!  I didn't even think about nesting it like that.  That'll work.
> 
> Many people seem to think that as much as possible should be done through type 
> extension. They act as though the only tool they have is the hammer of type 
> extension, and so view every problem as a nail. In my experience type extension 
> is usually best avoided whenever possible.
> 

Well, I think either form is a bit too polar.  I've always been taught that
you use the tool that makes the most sense given the context.  If a type
has an "is a" relationship, you favor extension.  But if it has a "has a"
relationship, you favor composition.  If the situation is unique enough,
then you do something outside the norm.

In this case I wasn't using extension because I thought it was the best
method.  I was using it because Ada doesn't provide me a good way to
rename a type as part of the full view.  Normally I would use subtype, 
but I can't do that with a private declaration (I don't want the client
to have access to the "subtypedness", but I want to leverage it under
the hood).  Extension was my first stab at it because of the natural
flow of type declarations in Ada.

I did run into a snag with using composition.  Some of my functions
return numeric or access types that are created within the generic
that I am trying to use.  I'll still have to do conversions for those
since I want them to retain their numeric and access properties (so
a private nested type won't do).

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

* Re: Full view of a private partial view cannot be a subtype
  2017-12-03 22:23       ` Jere
@ 2017-12-04  8:25         ` Dmitry A. Kazakov
  2017-12-04 18:04         ` Jeffrey R. Carter
  1 sibling, 0 replies; 46+ messages in thread
From: Dmitry A. Kazakov @ 2017-12-04  8:25 UTC (permalink / raw)


On 03/12/2017 23:23, Jere wrote:

> Well, I think either form is a bit too polar.  I've always been taught that
> you use the tool that makes the most sense given the context.  If a type
> has an "is a" relationship, you favor extension.  But if it has a "has a"
> relationship, you favor composition.  If the situation is unique enough,
> then you do something outside the norm.

These two are confusing. One is subtyping another is aggregation.

In your "is-a" the right part is a type or a class of types. E.g. X is a 
Integer = the type of X is a subtype of Integer or, alternatively, 
member of Integer'Class.

In your "has-a" the right part is a container, like String has 
Character. The left and right are unrelated types.

Now there is a "has-a" related to subtyping. Ada does not have that. It 
is a supertype. E.g. if you could declare an interface Numeric and hang 
it on an existing type Integer:

    type Number is old Integer; -- (:-))
or
    supertype Number is Integer <wider range, other numbers>;

Numeric has an Integer = Integer is a Numeric.

Then extension is irrelevant to either "is-a" or "has-a" subtyping 
relation. It is an implementation detail regarding representations of 
two related types. You could have "is-a" with, without extension or 
completely abandoning another type representation, but not in Ada. Ada 
glues interface and representation together. That was an unfortunate 
design choice motivated by premature optimization in order to have view 
conversions.

> In this case I wasn't using extension because I thought it was the best
> method.  I was using it because Ada doesn't provide me a good way to
> rename a type as part of the full view.  Normally I would use subtype,
> but I can't do that with a private declaration (I don't want the client
> to have access to the "subtypedness", but I want to leverage it under
> the hood).  Extension was my first stab at it because of the natural
> flow of type declarations in Ada.

Ada's subtype is another method to implement "is-a"/"has-a" 
relationships by borrowing representation and putting constraints. It is 
"is-a" for in-parameters, "has-a" for out-parameters. It is neither 
worse or better than extension, it is different.

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


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

* Re: Full view of a private partial view cannot be a subtype
  2017-12-03 22:23       ` Jere
  2017-12-04  8:25         ` Dmitry A. Kazakov
@ 2017-12-04 18:04         ` Jeffrey R. Carter
  2017-12-04 20:41           ` Jere
  1 sibling, 1 reply; 46+ messages in thread
From: Jeffrey R. Carter @ 2017-12-04 18:04 UTC (permalink / raw)


On 12/03/2017 11:23 PM, Jere wrote:
> 
> Well, I think either form is a bit too polar.  I've always been taught that
> you use the tool that makes the most sense given the context.  If a type
> has an "is a" relationship, you favor extension.  But if it has a "has a"
> relationship, you favor composition.  If the situation is unique enough,
> then you do something outside the norm.

The most important thing is to create the simplest and clearest code possible. 
Tools must be judged by how well they help achieve this. Between type extension 
and composition, composition is almost always easier to read and understand.

-- 
Jeff Carter
"I would never want to belong to any club that
would have someone like me for a member."
Annie Hall
41


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

* Re: Full view of a private partial view cannot be a subtype
  2017-12-04 18:04         ` Jeffrey R. Carter
@ 2017-12-04 20:41           ` Jere
  2017-12-04 21:48             ` Jeffrey R. Carter
  0 siblings, 1 reply; 46+ messages in thread
From: Jere @ 2017-12-04 20:41 UTC (permalink / raw)


On Monday, December 4, 2017 at 1:04:28 PM UTC-5, Jeffrey R. Carter wrote:
> On 12/03/2017 11:23 PM, Jere wrote:
> > 
> > Well, I think either form is a bit too polar.  I've always been taught that
> > you use the tool that makes the most sense given the context.  If a type
> > has an "is a" relationship, you favor extension.  But if it has a "has a"
> > relationship, you favor composition.  If the situation is unique enough,
> > then you do something outside the norm.
> 
> The most important thing is to create the simplest and clearest code possible. 
> Tools must be judged by how well they help achieve this. Between type extension 
> and composition, composition is almost always easier to read and understand.
> 
I don't disagree in general per say, but that is a very subjective thing.  I
don't find composition nearly as readable as you do.  It has it's place and
can be more readable, but (maybe it's just how I read and visualize) I find
extension to be more readable in probably more cases than you typically do.  
It's just a personal thing with how I read.  I've used and written both. 

In the case of the topic at hand, I do think composition leads to cleaner
more readable code.  I do still get stuck with some extra "noisy" 
conversions, but way less than the extension method in this case.

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

* Re: Full view of a private partial view cannot be a subtype
  2017-12-03  2:14 Full view of a private partial view cannot be a subtype Jere
  2017-12-03 12:01 ` Jeffrey R. Carter
@ 2017-12-04 20:49 ` Randy Brukardt
  2017-12-05 12:56   ` Jere
  2017-12-18 20:45 ` Stephen Leake
  2 siblings, 1 reply; 46+ messages in thread
From: Randy Brukardt @ 2017-12-04 20:49 UTC (permalink / raw)


"Jere" <jhb.chat@gmail.com> wrote in message 
news:c6ba70e3-bfd0-42ca-b742-dc472965eea0@googlegroups.com...
...
>   package New_Type1 is
>      subtype Instance is Base.Instance;
>      procedure Operation(Object : in out Instance);
>
>   private
>
>      procedure Operation(Object : in out Instance) renames Base.Operation;
>   end New_Type1;
>
> (NOTE:  is there a better way to do this?)

No, no better way yet, but maybe (large maybe here) in Ada 2020. (I'm 
leaving out all details because none have been determined yet and perhaps 
never will be for Ada 2020.)

> This is all well and good, but sometimes while I as an implementer
> want this kind of relationship, I don't necessarily want to expose
> that relationship outside the private section of a package.  Here I
> run into a problem as I cannot (as far as I can tell) do:
>
>   package New_Type2 is
>      type Instance is tagged limited private;
>      procedure Operation(Object : in out Instance);
>   private
>      subtype Instance is Base.Instance;

This is illegal; a private type has to be completed with a full type, not a 
subtype. (If you have a compiler that is allowing this, it is confused...)

>      procedure Operation(Object : in out Instance) renames Base.Operation;

...which makes Instance a different type, and that makes this illegal (if 
the type declaration is written properly).

>   end New_Type2;

Usually, you're better off allowing the relationship between types to be 
visible. In that case, this happens automatically.

Otherwise, you can usually do this with this a "squirreling" rename 
(essentially, you have to rename the inherited entity before declaring the 
new one). However, in this case, you've hidden the inherited operation 
before you can rename it, so you can't do this. If you wanted a different 
operation name, it would work:

   package New_Type3 is
      type Instance is tagged limited private;
      procedure Other_Operation(Object : in out Instance);
  private
      type Instance is new Base.Instance with record ... end record;

     procedure Other_Operation(Object : in out Instance) renames 
Operation; -- (1)

  end New_Type3;

At (1), you are renaming the operation inherited from Base.Instance. That 
operation isn't visible to clients, only within this package. And it has the 
correct types.

The main use for a "squirrelling" rename is to be able to call the original 
operation in a overridden operation:

   package New_Type4 is
      type Instance is new Base.Instance with record ... end record;
      -- Operation is inherited here, with the profile:
      --procedure Operation (Object : in out Instance);
  private

     procedure Original_Operation(Object : in out Instance) renames 
Operation; -- (1)
     overriding
     procedure Operation (Object : in out Instance);
  end New_Type4;

The declaration at (1) allows the body of Operation to call the body of 
Base.Operation (but with the proper types).

                           Randy.




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

* Re: Full view of a private partial view cannot be a subtype
  2017-12-04 20:41           ` Jere
@ 2017-12-04 21:48             ` Jeffrey R. Carter
  2017-12-05  8:20               ` Dmitry A. Kazakov
                                 ` (3 more replies)
  0 siblings, 4 replies; 46+ messages in thread
From: Jeffrey R. Carter @ 2017-12-04 21:48 UTC (permalink / raw)


On 12/04/2017 09:41 PM, Jere wrote:
>>
> I don't disagree in general per say, but that is a very subjective thing.  I
> don't find composition nearly as readable as you do.  It has it's place and
> can be more readable, but (maybe it's just how I read and visualize) I find
> extension to be more readable in probably more cases than you typically do.
> It's just a personal thing with how I read.  I've used and written both.

I've never seen a realistic problem that was as readable when implemented with 
type extension as with composition.

Perhaps the best fit of any problem with type extension is a GUI framework, 
since everything "is-a" widget. I have used 2 such frameworks implemented using 
type extension, Claw and Gnoga, and both are very difficult to understand. The 
derivation trees are very deep and there are a huge number of inherited 
operations. It's effectively impossible to know all the operations for the most 
commonly used types, which tend to be down at the leaves of the derivation tree. 
Sometimes an operation behaves differently at different levels, with no 
indication that this should be expected. Even with a tool like GPS, which will 
bring up a list of completions when you type a dot after the name of something 
of a tagged type, is not very helpful when the list contains hundreds of 
possibilities. One tends to stick with the basics described in the examples and 
add a few additional things through experimentation, leaving a great deal of 
poorly understood and unused functionality in the framework.

With a composition approach you would at a minimum have a list of every 
operation on every type right there with the type declaration.

On real code at work I have seen 4 experienced people spend a half an hour 
analyzing a piece of code, tracing through the spaghetti of type extensions and 
dispatching to figure out what it was doing. Those 2 wasted person-hours could 
have been reduced by a factor of 4 or more had type extension been eschewed.

I have been looking at this for over 2 decades and have yet to see a 
counterexample. If you think you know of one I'd like to see it. Maybe I'm weird 
and most people have no problem understanding these things, but I've seen plenty 
of other experienced people have similar difficulties, so I doubt it.

JP Rosen wrote a paper, "What Orientation Should Ada's Objects Take?" (IIRC) 
that reached a similar conclusion.

-- 
Jeff Carter
"I would never want to belong to any club that
would have someone like me for a member."
Annie Hall
41


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

* Re: Full view of a private partial view cannot be a subtype
  2017-12-04 21:48             ` Jeffrey R. Carter
@ 2017-12-05  8:20               ` Dmitry A. Kazakov
  2017-12-05 18:16                 ` Jeffrey R. Carter
  2017-12-05 12:35               ` Jere
                                 ` (2 subsequent siblings)
  3 siblings, 1 reply; 46+ messages in thread
From: Dmitry A. Kazakov @ 2017-12-05  8:20 UTC (permalink / raw)


On 04/12/2017 22:48, Jeffrey R. Carter wrote:

> With a composition approach you would at a minimum have a list of every 
> operation on every type right there with the type declaration.

Overloaded with the same operations from other widget types.

The fallacy of the argument comes straight from the point that the 
number of operation is just same. GPS is far worse in finding overloaded 
operations.

If Button, Toggle_Button, Radio_Button etc were unrelated then in each 
event handler within a monstrous case over all possible widgets emitting 
the event, good luck finding their operations, cutting and pasting same 
code, you cannot reuse because types are unrelated. Yes, generics they 
will serve the final stroke to this insanity.

> I have been looking at this for over 2 decades and have yet to see a 
> counterexample. If you think you know of one I'd like to see it. Maybe 
> I'm weird and most people have no problem understanding these things, 
> but I've seen plenty of other experienced people have similar 
> difficulties, so I doubt it.

There are no more GUI frameworks based on overloading. Aggregation is 
used only for parent-child widget relationship.

You are welcome to propose one. After all it is only the interface you 
have to design. All the implementation can be based on an existing 
framework with inheritance and overriding...

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

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

* Re: Full view of a private partial view cannot be a subtype
  2017-12-04 21:48             ` Jeffrey R. Carter
  2017-12-05  8:20               ` Dmitry A. Kazakov
@ 2017-12-05 12:35               ` Jere
  2017-12-05 18:40                 ` Jeffrey R. Carter
  2017-12-05 20:22                 ` Randy Brukardt
  2017-12-05 15:27               ` Shark8
  2017-12-05 20:16               ` Randy Brukardt
  3 siblings, 2 replies; 46+ messages in thread
From: Jere @ 2017-12-05 12:35 UTC (permalink / raw)


On Monday, December 4, 2017 at 4:48:34 PM UTC-5, Jeffrey R. Carter wrote:
> On 12/04/2017 09:41 PM, Jere wrote:
> >>
> > I don't disagree in general per say, but that is a very subjective thing.  I
> > don't find composition nearly as readable as you do.  It has it's place and
> > can be more readable, but (maybe it's just how I read and visualize) I find
> > extension to be more readable in probably more cases than you typically do.
> > It's just a personal thing with how I read.  I've used and written both.
> 
> I've never seen a realistic problem that was as readable when implemented with 
> type extension as with composition.
> 
> Perhaps the best fit of any problem with type extension is a GUI framework, 
> since everything "is-a" widget. I have used 2 such frameworks implemented using 
> type extension, Claw and Gnoga, and both are very difficult to understand. The 
> derivation trees are very deep and there are a huge number of inherited 
> operations. It's effectively impossible to know all the operations for the most 
> commonly used types, which tend to be down at the leaves of the derivation tree. 
> Sometimes an operation behaves differently at different levels, with no 
> indication that this should be expected. Even with a tool like GPS, which will 
> bring up a list of completions when you type a dot after the name of something 
> of a tagged type, is not very helpful when the list contains hundreds of 
> possibilities. One tends to stick with the basics described in the examples and 
> add a few additional things through experimentation, leaving a great deal of 
> poorly understood and unused functionality in the framework.
> 

You run into the same issues with composition (only in my view worse).  With
composition you still have to look up each component's file to see it's
operations and worse yet you have no tools that can help you extrapolate
what operations are available from a higher level component.  With extension
you can at least use auto completion lists to see what all the options are.
With composition you are stuck doing X.<see list> then X.Y.<see list> then
X.Y.Z.<see list> and so on.  Then the component chaining when wanting to call
an ancestor's operation can quickly blow up with composition (as opposed to
extension where there is a single level).  You can simplify this by creating
forwarding functions in the higher level components, but that is analogous
to adding overloads in the higher level components for extension.  For either
it is optional.


> With a composition approach you would at a minimum have a list of every 
> operation on every type right there with the type declaration.
This phrasing makes me think you are comparing private composition vs
public extension.  If so, it would be more fair to compare private
composition vs private extension.  Both of those require at a minimum 
have a list of every operation on every type right there with the type 
declaration.  Perhaps this is really more an issue of private vs public
inheritance?

> 
> On real code at work I have seen 4 experienced people spend a half an hour 
> analyzing a piece of code, tracing through the spaghetti of type extensions and 
> dispatching to figure out what it was doing. Those 2 wasted person-hours could 
> have been reduced by a factor of 4 or more had type extension been eschewed.
> 
> I have been looking at this for over 2 decades and have yet to see a 
> counterexample. If you think you know of one I'd like to see it. Maybe I'm weird 
> and most people have no problem understanding these things, but I've seen plenty 
> of other experienced people have similar difficulties, so I doubt it.
> 
> JP Rosen wrote a paper, "What Orientation Should Ada's Objects Take?" (IIRC) 
> that reached a similar conclusion.
> 

I respect yall's view on this, but in either case it is still a subjective
matter.  There are a variety of people out there who all view things very
differently.

On a side note, I hope I do not sound too combative.  I really do appreciate
your input and your views.  I've read most of your papers and have enjoyed
them.  Even if I don't agree with a specific point, I still try to re-evaluate
my own decision based on what you are suggesting.

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

* Re: Full view of a private partial view cannot be a subtype
  2017-12-04 20:49 ` Randy Brukardt
@ 2017-12-05 12:56   ` Jere
  2017-12-05 20:12     ` Randy Brukardt
  0 siblings, 1 reply; 46+ messages in thread
From: Jere @ 2017-12-05 12:56 UTC (permalink / raw)


On Monday, December 4, 2017 at 3:49:54 PM UTC-5, Randy Brukardt wrote:
> "Jere" wrote in message 
> ...
> >   package New_Type1 is
> >      subtype Instance is Base.Instance;
> >      procedure Operation(Object : in out Instance);
> >
> >   private
> >
> >      procedure Operation(Object : in out Instance) renames Base.Operation;
> >   end New_Type1;
> >
> > (NOTE:  is there a better way to do this?)
> 
> No, no better way yet, but maybe (large maybe here) in Ada 2020. (I'm 
> leaving out all details because none have been determined yet and perhaps 
> never will be for Ada 2020.)

Sounds intriguing!

> 
> > This is all well and good, but sometimes while I as an implementer
> > want this kind of relationship, I don't necessarily want to expose
> > that relationship outside the private section of a package.  Here I
> > run into a problem as I cannot (as far as I can tell) do:
> >
> >   package New_Type2 is
> >      type Instance is tagged limited private;
> >      procedure Operation(Object : in out Instance);
> >   private
> >      subtype Instance is Base.Instance;
> 
> This is illegal; a private type has to be completed with a full type, not a 
> subtype. (If you have a compiler that is allowing this, it is confused...)

Yep, that was my comment.  Basically I have a low level package that is used
to create many higher level, more client friendly packages:

generic 
   type Input_Type(<>);
   with procedure Really_Dangerous_To_Call(Object : Input_Type);
   Value : Integer;
package Low_Level_Package

   type My_Type is private;
   type Numeric_Type is <some implementation using Value>;

   function Client_Friendly_Procedure
     (Object : My_Type)
      return Numeric_Type;

   <other operations>

private
   ...

end Low_Level_Package;

and I want to use it to make some more client friendly versions.
The procedure, Really_Dangerous_To_Call, isn't meant to be called
directly for a client.  It is meant to be used to setup implementations
behind the client packages.  At current my choices seem to be:

subtyping:

generic 
   type Input_Type is limited private;
package High_Level_Package

   procedure Client_Please_Do_Not_Call(Object : Input_Type);
   package I_Really_Wanted_To_Hide_You is new Low_Level_Package
      (Input_Type               => Input_Type,
       Really_Dangerous_To_Call => Client_Please_Do_Not_Call,
       Value                    => <some value>);

   subtype My_Type is I_Really_Wanted_To_Hide_You.My_Type;
   subtype Numeric_Type is I_Really_Wanted_To_Hide_You.Numeric_Type

   function Client_Friendly_Procedure
     (Object : My_Type)
      return Numeric_Type
      renames I_Really_Wanted_To_Hide_You.Client_Friendly_Procedure;

   <other operations>

end High_Level_Package;

which exposes operations and values I do not want to expose in a more
client friendly package.  Currently in Ada there isn't a way that I
have found to use subtyping for this in a private manner.

Instead I either need to bite the bullet and expose those details (ugh),
or I need to use extension or composition, of which composition is
less noisy, but both will end up requiring some noisy code and
possibly extra unnecessary overhead (depending on how the type 
conversions work out).  So here the tradeoff appears to be
readability vs overhead, which I don't feel it needs to be in this
case, but I haven't found a good Ada building block that gives me
both.


> <SNIPPED>
> At (1), you are renaming the operation inherited from Base.Instance. That 
> operation isn't visible to clients, only within this package. And it has the 
> correct types.
> 
> The main use for a "squirrelling" rename is to be able to call the original 
> operation in a overridden operation:
> 
>    package New_Type4 is
>       type Instance is new Base.Instance with record ... end record;
>       -- Operation is inherited here, with the profile:
>       --procedure Operation (Object : in out Instance);
>   private
> 
>      procedure Original_Operation(Object : in out Instance) renames 
> Operation; -- (1)
>      overriding
>      procedure Operation (Object : in out Instance);
>   end New_Type4;
> 
> The declaration at (1) allows the body of Operation to call the body of 
> Base.Operation (but with the proper types).
> 
>                            Randy.

This is an option I use sometimes.  In this case I was hoping to keep all 
the interfaces named the same.

I typed this up hurriedly, so I apologize if I made a typo.  I hope the
meaning is conveyed better though.

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

* Re: Full view of a private partial view cannot be a subtype
  2017-12-04 21:48             ` Jeffrey R. Carter
  2017-12-05  8:20               ` Dmitry A. Kazakov
  2017-12-05 12:35               ` Jere
@ 2017-12-05 15:27               ` Shark8
  2017-12-05 18:50                 ` Jeffrey R. Carter
  2017-12-05 20:59                 ` Randy Brukardt
  2017-12-05 20:16               ` Randy Brukardt
  3 siblings, 2 replies; 46+ messages in thread
From: Shark8 @ 2017-12-05 15:27 UTC (permalink / raw)


On Monday, December 4, 2017 at 2:48:34 PM UTC-7, Jeffrey R. Carter wrote:
> On 12/04/2017 09:41 PM, Jere wrote:
> >>
> > I don't disagree in general per say, but that is a very subjective thing.  I
> > don't find composition nearly as readable as you do.  It has it's place and
> > can be more readable, but (maybe it's just how I read and visualize) I find
> > extension to be more readable in probably more cases than you typically do.
> > It's just a personal thing with how I read.  I've used and written both.
> 
> I've never seen a realistic problem that was as readable when implemented with 
> type extension as with composition.
> 
> Perhaps the best fit of any problem with type extension is a GUI framework, 
> since everything "is-a" widget. I have used 2 such frameworks implemented using 
> type extension, Claw and Gnoga, and both are very difficult to understand. The 
> derivation trees are very deep and there are a huge number of inherited 
> operations. It's effectively impossible to know all the operations for the most 
> commonly used types, which tend to be down at the leaves of the derivation tree. 

One of the best GUI frameworks I've seen is Delphi's VCL -- it is very good in this respect having several "base level" types where you'll look for common operations. (There's one for visual-components, one for nonvisual-components, and they both share an ancestor that is [IIRC] higher than TObject.)

Besides UIs, the one problem that springs immediately to mind is the internals of a compiler's IR/parse-tree. Another is linguistics (though I haven't actually seen this used) where you are modelling language on a abstract/general level: Types Verb & Noun, descending from Word. Phrases, sentences, etc.

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

* Re: Full view of a private partial view cannot be a subtype
  2017-12-05  8:20               ` Dmitry A. Kazakov
@ 2017-12-05 18:16                 ` Jeffrey R. Carter
  2017-12-05 20:39                   ` Dmitry A. Kazakov
  0 siblings, 1 reply; 46+ messages in thread
From: Jeffrey R. Carter @ 2017-12-05 18:16 UTC (permalink / raw)


On 12/05/2017 09:20 AM, Dmitry A. Kazakov wrote:
> 
> If Button, Toggle_Button, Radio_Button etc were unrelated then in each event 
> handler within a monstrous case over all possible widgets emitting the event, 
> good luck finding their operations, cutting and pasting same code, you cannot 
> reuse because types are unrelated. Yes, generics they will serve the final 
> stroke to this insanity.

If that were really the way you'd design such a thing if deprived of type 
extension then I would to think you were incompetent to design S/W. I wouldn't 
do it that way.

> You are welcome to propose one. After all it is only the interface you have to 
> design. All the implementation can be based on an existing framework with 
> inheritance and overriding...

The problem with trying to build such a layer on top of an existing framework is 
that they all use the C-inspired idea of giving up your thread of control to the 
framework and it making calls to code you provide. That's not how it should be 
done in a decent language.

-- 
Jeff Carter
"I did not rob a bank. If I'd robbed a bank, everything
would be great. I tried to rob a bank, is what happened,
and they got me."
Take the Money and Run
139


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

* Re: Full view of a private partial view cannot be a subtype
  2017-12-05 12:35               ` Jere
@ 2017-12-05 18:40                 ` Jeffrey R. Carter
  2017-12-06 12:54                   ` Jere
  2017-12-05 20:22                 ` Randy Brukardt
  1 sibling, 1 reply; 46+ messages in thread
From: Jeffrey R. Carter @ 2017-12-05 18:40 UTC (permalink / raw)


On 12/05/2017 01:35 PM, Jere wrote:
> 
> You run into the same issues with composition (only in my view worse).  With
> composition you still have to look up each component's file to see it's
> operations and worse yet you have no tools that can help you extrapolate
> what operations are available from a higher level component.  With extension
> you can at least use auto completion lists to see what all the options are.
> With composition you are stuck doing X.<see list> then X.Y.<see list> then
> X.Y.Z.<see list> and so on.  Then the component chaining when wanting to call
> an ancestor's operation can quickly blow up with composition (as opposed to
> extension where there is a single level).  You can simplify this by creating
> forwarding functions in the higher level components, but that is analogous
> to adding overloads in the higher level components for extension.  For either
> it is optional.

If you're lucky enough to have such a tool. I still find myself reading code 
without such assistance often enough that I think that code that is only 
readable with a tool is not readable at all.

But your argument is about ease of writing, with isn't going to convince anyone 
who likes Ada. Ada explicitly states in the ARM Introduction that it's for code 
that's easy to read, not easy to write. The fact that you type more with 
composition is not an argument against it.

But in my design a client wouldn't have X.Y.Z... It would apply an operation to 
a variant record X and the operation would do the correct thing for the current 
variant. If you needed to find the actual code executed without a tool, there's 
a chain of with clauses to lead you to it. You don't end up looking at an 
abstract subprogram with no idea where the actual subprogram is.

> I respect yall's view on this, but in either case it is still a subjective
> matter.  There are a variety of people out there who all view things very
> differently.

I disagree. There are a set of S/W-engineering principles that help guide the 
S/W engineer to create S/W that is simple, correct, and easy to read. Every 
real-world use of type extension that I've seen has violated the principle of 
locality--that's inherent in the nature of type extension. Thus it is 
objectively more complex and harder to read than S/W that violates none of the 
principles.

-- 
Jeff Carter
"I did not rob a bank. If I'd robbed a bank, everything
would be great. I tried to rob a bank, is what happened,
and they got me."
Take the Money and Run
139


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

* Re: Full view of a private partial view cannot be a subtype
  2017-12-05 15:27               ` Shark8
@ 2017-12-05 18:50                 ` Jeffrey R. Carter
  2017-12-05 20:59                 ` Randy Brukardt
  1 sibling, 0 replies; 46+ messages in thread
From: Jeffrey R. Carter @ 2017-12-05 18:50 UTC (permalink / raw)


On 12/05/2017 04:27 PM, Shark8 wrote:
> 
> Besides UIs, the one problem that springs immediately to mind is the internals of a compiler's IR/parse-tree. Another is linguistics (though I haven't actually seen this used) where you are modelling language on a abstract/general level: Types Verb & Noun, descending from Word. Phrases, sentences, etc.

Do most compilers use type extension for that? If not, it would be interesting 
to know why.

-- 
Jeff Carter
"I did not rob a bank. If I'd robbed a bank, everything
would be great. I tried to rob a bank, is what happened,
and they got me."
Take the Money and Run
139


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

* Re: Full view of a private partial view cannot be a subtype
  2017-12-05 12:56   ` Jere
@ 2017-12-05 20:12     ` Randy Brukardt
  2017-12-17 15:26       ` Jere
  0 siblings, 1 reply; 46+ messages in thread
From: Randy Brukardt @ 2017-12-05 20:12 UTC (permalink / raw)


"Jere" <jhb.chat@gmail.com> wrote in message 
news:5b32a99e-04e5-4adb-8b42-88e485570641@googlegroups.com...
> On Monday, December 4, 2017 at 3:49:54 PM UTC-5, Randy Brukardt wrote:
>> "Jere" wrote in message
>> ...
>> >   package New_Type1 is
>> >      subtype Instance is Base.Instance;
>> >      procedure Operation(Object : in out Instance);
>> >
>> >   private
>> >
>> >      procedure Operation(Object : in out Instance) renames 
>> > Base.Operation;
>> >   end New_Type1;
>> >
>> > (NOTE:  is there a better way to do this?)
>>
>> No, no better way yet, but maybe (large maybe here) in Ada 2020. (I'm
>> leaving out all details because none have been determined yet and perhaps
>> never will be for Ada 2020.)
>
> Sounds intriguing!
>
>>
>> > This is all well and good, but sometimes while I as an implementer
>> > want this kind of relationship, I don't necessarily want to expose
>> > that relationship outside the private section of a package.  Here I
>> > run into a problem as I cannot (as far as I can tell) do:
>> >
>> >   package New_Type2 is
>> >      type Instance is tagged limited private;
>> >      procedure Operation(Object : in out Instance);
>> >   private
>> >      subtype Instance is Base.Instance;
>>
>> This is illegal; a private type has to be completed with a full type, not 
>> a
>> subtype. (If you have a compiler that is allowing this, it is 
>> confused...)
>
> Yep, that was my comment.  Basically I have a low level package that is 
> used
> to create many higher level, more client friendly packages:
>
> generic
>   type Input_Type(<>);
>   with procedure Really_Dangerous_To_Call(Object : Input_Type);
>   Value : Integer;
> package Low_Level_Package
>
>   type My_Type is private;
>   type Numeric_Type is <some implementation using Value>;
>
>   function Client_Friendly_Procedure
>     (Object : My_Type)
>      return Numeric_Type;
>
>   <other operations>
>
> private
>   ...
>
> end Low_Level_Package;
>
> and I want to use it to make some more client friendly versions.
> The procedure, Really_Dangerous_To_Call, isn't meant to be called
> directly for a client.  It is meant to be used to setup implementations
> behind the client packages.

If you control the entire design of the type hierarchy, the best way to do 
this is to put "Really_Dangerous_to_Call" into the private part of the root 
operation, and declare the child types in child packages. Then, the child 
types can call the routine but clients cannot. (An added advantage is that 
Really_Dangerous_to_Call can be dispatching in such a design.)

Claw is organized this way, so it's pretty certain that Ada compilers can 
properly process such an organization.

This looks something like:

    package Claw is
        ... -- Hundreds of lines of other stuff...

        type Root_Window_Type is abstract tagged private; -- Actually, 
derived from Controlled.

        ... -- Public dispatching operations available for all Windows, like 
Move, Resize, etc.

   private

        procedure Really_Dangerous_to_Call (Window : in out 
Root_Window_Type);

        -- Other private dispatching operations and the full declaration of 
Root_Window_Type.
   end Claw;

   package Claw.Basic is
        type Basic_Window_Type is new Root_Window_Type with private;

        ... -- Public for Basic_Windows, including those available for all 
Windows, like Move, Resize, etc.

   private

        -- Can override Really_Dangerous_to_Call here, if needed.

   end Claw.Basic;

The body of Claw.Basic can call Really_Dangerous_to_Call if needed, but 
clients can't. If you only need class-wide operations, you can also do this 
with a private package (which then can only be withed by children of the 
parent package, and not visibly).

Claw uses this to hide the actual message handlers from the clients (so the 
client can't mess them up), and uses dispatching to call them (so each Claw 
type can have a custom message handler if needed -- and it is usually 
needed).

                                      Randy.



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

* Re: Full view of a private partial view cannot be a subtype
  2017-12-04 21:48             ` Jeffrey R. Carter
                                 ` (2 preceding siblings ...)
  2017-12-05 15:27               ` Shark8
@ 2017-12-05 20:16               ` Randy Brukardt
  2017-12-05 21:29                 ` Jeffrey R. Carter
  3 siblings, 1 reply; 46+ messages in thread
From: Randy Brukardt @ 2017-12-05 20:16 UTC (permalink / raw)


"Jeffrey R. Carter" <spam.jrcarter.not@spam.not.acm.org> wrote in message 
news:p04frg$q8n$1@dont-email.me...
...
> Perhaps the best fit of any problem with type extension is a GUI 
> framework, since everything "is-a" widget. I have used 2 such frameworks 
> implemented using type extension, Claw and Gnoga, and both are very 
> difficult to understand. The derivation trees are very deep and there are 
> a huge number of inherited operations. It's effectively impossible to know 
> all the operations for the most commonly used types, which tend to be down 
> at the leaves of the derivation tree.

Not impossible, just impossible by reading the source code. The Claw 
documentation materializes all of the inherited routines so that there is a 
cohesive list of all of the operations available for each time in the 
documentation. (Needless to say, this documentation is generated by an 
automated tool with annotations.)

...
> Sometimes an operation behaves differently at different levels, with no 
> indication that this should be expected.

Reading the super-secret documentation would help, I hope. ;-)

I realize that real programmers don't need (or look at) documentation, but 
it is impossible to convey everything important in Ada source code!

                               Randy.



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

* Re: Full view of a private partial view cannot be a subtype
  2017-12-05 12:35               ` Jere
  2017-12-05 18:40                 ` Jeffrey R. Carter
@ 2017-12-05 20:22                 ` Randy Brukardt
  1 sibling, 0 replies; 46+ messages in thread
From: Randy Brukardt @ 2017-12-05 20:22 UTC (permalink / raw)


"Jere" <jhb.chat@gmail.com> wrote in message 
news:c6fef139-6718-4c05-8791-897e995bdb4c@googlegroups.com...
> On Monday, December 4, 2017 at 4:48:34 PM UTC-5, Jeffrey R. Carter wrote:
...
> I respect yall's view on this, but in either case it is still a subjective
> matter.  There are a variety of people out there who all view things very
> differently.

Jeff's opinion on type extension seems to be the most extreme here on c.l.a 
so that isn't surprising. (Full discloser: I'm probably the second-most 
extreme.)


                              Randy. 



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

* Re: Full view of a private partial view cannot be a subtype
  2017-12-05 18:16                 ` Jeffrey R. Carter
@ 2017-12-05 20:39                   ` Dmitry A. Kazakov
  2017-12-05 21:38                     ` Jeffrey R. Carter
  0 siblings, 1 reply; 46+ messages in thread
From: Dmitry A. Kazakov @ 2017-12-05 20:39 UTC (permalink / raw)


On 2017-12-05 19:16, Jeffrey R. Carter wrote:
> On 12/05/2017 09:20 AM, Dmitry A. Kazakov wrote:
>>
>> If Button, Toggle_Button, Radio_Button etc were unrelated then in each 
>> event handler within a monstrous case over all possible widgets 
>> emitting the event, good luck finding their operations, cutting and 
>> pasting same code, you cannot reuse because types are unrelated. Yes, 
>> generics they will serve the final stroke to this insanity.
> 
> If that were really the way you'd design such a thing if deprived of 
> type extension then I would to think you were incompetent to design S/W. 
> I wouldn't do it that way.

It was your idea not mine. Either buttons are related types or not.

There are three relationships between widgets:

1. Parent-child

2. Commonalities in widget appearance and functionality, e.g. buttons, 
menus etc

3. Publisher-subscriber to events, messages, signals

The classic GUI design uses referential aggregation for #1, [multiple] 
inheritance for #2, weak references for #3.

It is simply impossible to use aggregation for everything just because 
aggregation is hierarchic. It can be only one thing you could put there.

>> You are welcome to propose one. After all it is only the interface you 
>> have to design. All the implementation can be based on an existing 
>> framework with inheritance and overriding...
> 
> The problem with trying to build such a layer on top of an existing 
> framework is that they all use the C-inspired idea of giving up your 
> thread of control to the framework and it making calls to code you 
> provide. That's not how it should be done in a decent language.

Firstly, it has no influence on the interface design. Secondly, you can 
always use a task monitor and route all calls through it.

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


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

* Re: Full view of a private partial view cannot be a subtype
  2017-12-05 15:27               ` Shark8
  2017-12-05 18:50                 ` Jeffrey R. Carter
@ 2017-12-05 20:59                 ` Randy Brukardt
  2017-12-05 22:43                   ` Shark8
  1 sibling, 1 reply; 46+ messages in thread
From: Randy Brukardt @ 2017-12-05 20:59 UTC (permalink / raw)


"Shark8" <onewingedshark@gmail.com> wrote in message 
news:43498b2a-773c-454a-b0e7-ade5d6594bd4@googlegroups.com...
...
>Besides UIs, the one problem that springs immediately to mind is the 
>internals of a
>compiler's IR/parse-tree.

I can speak to this (at least somewhat), and I think the full OOP version 
would be a nightmare.

Janus/Ada (originally designed in the early 1980s, before there was such a 
thing as type extension) uses variant records controlled by enumeration 
discriminants. That is a very effective organization in Ada, because of two 
features of Ada not found in most other languages - case completeness and 
variant component checks.

Case completeness means that adding/removing a variant is relatively easy: 
most case statements that need changing are called out by the compiler. Time 
has proven that it isn't even worth looking for change locations since the 
compiler will point them out much quicker than one can find them. Similarly, 
adding/removing/moving/modifying components in the variant either cause 
compiler errors (see above) or runtime errors from accessing non-existent 
components. With good testing (easy for an Ada compiler - the ACATS provides 
the needed foundation), the runtime errors will point out the majority of 
other changes needed. Indeed, I've been introducing additional variants into 
the Janus/Ada data structures in order to get even more advantage from these 
features -- they eliminate large amounts of debugging that would otherwise 
been necessary.

I've never tried an OOP compiler tree, but the Claw Builder uses an OOP 
organization both for the GUI and for the code generation. And that did not 
really work out well. There is so much boilerplate that has to be 
constructed for every new widget type (to declare all of the overriding 
routines, to provide basic implementations for those routines, and the like) 
that there is a strong dis-incentive to adding new widgets. (The last time I 
tried to add a widget, it took over 2 days solid coding to get to a 
compilable type.) And the boilerplate didn't seem (for Ada) to make anything 
easier to implement or debug.

Similarly, adding a new kind of code generation (something that happens 
frequently with the Builder, probably would happen fairly often for a 
compiler as well) is a nightmare, as the new dispatching routine has to be 
added to every existing widget.

By abandoning traditional OOP, one could do a bit better (especially by 
implementing many concrete operations in the root classes -- meaning, in Ada 
terms, that they can't be interfaces), and maybe some of the boilerplate 
could be reduced - but to do so, you'd have to introduce even more 
operations. The number of dispatching operations alone was becoming 
daunting.

Thus, I'm unconvinced that a compiler data structure would be any advantage 
written in OOP (at least, if the "conventional" version was written in Ada). 
I suspect the reason that OOP held some much advantage to many programmers 
(read, C programmers) is that they had a language which provided no help at 
all for "conventional" programming, while Ada already had information 
hiding, true privacy, case completeness, variant component checks, array 
index checks, etc. So the increment is so much less.

I think the only place OOP really holds an advantage is for programs based 
around call-backs (like most GUIs). And I think you'd be nuts to use 
call-backs if you don't have to, so there isn't much need for OOP (assuming 
it is compared to "conventional" Ada and some some other language that lets 
one do anything, no matter how unintended).

                                                 Randy.



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

* Re: Full view of a private partial view cannot be a subtype
  2017-12-05 20:16               ` Randy Brukardt
@ 2017-12-05 21:29                 ` Jeffrey R. Carter
  2017-12-07  0:04                   ` Randy Brukardt
  0 siblings, 1 reply; 46+ messages in thread
From: Jeffrey R. Carter @ 2017-12-05 21:29 UTC (permalink / raw)


On 12/05/2017 09:16 PM, Randy Brukardt wrote:
> 
> Not impossible, just impossible by reading the source code. The Claw
> documentation materializes all of the inherited routines so that there is a
> cohesive list of all of the operations available for each time in the
> documentation. (Needless to say, this documentation is generated by an
> automated tool with annotations.)

By "know", I mean keep in my head. Like Dijkstra, I have only a small brain, and 
have to figure out ways to deal with my inability to keep an entire S/W system 
in my head at once. So for me, at least, even with that it's impossible. You 
big-brained types might have it easier.

> Reading the super-secret documentation would help, I hope. ;-)

For the real cases I've experienced recently, I think I read everything available.

> I realize that real programmers don't need (or look at) documentation, but
> it is impossible to convey everything important in Ada source code!

Clearly that needs to be fixed in Ada 2X.

-- 
Jeff Carter
"I did not rob a bank. If I'd robbed a bank, everything
would be great. I tried to rob a bank, is what happened,
and they got me."
Take the Money and Run
139


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

* Re: Full view of a private partial view cannot be a subtype
  2017-12-05 20:39                   ` Dmitry A. Kazakov
@ 2017-12-05 21:38                     ` Jeffrey R. Carter
  0 siblings, 0 replies; 46+ messages in thread
From: Jeffrey R. Carter @ 2017-12-05 21:38 UTC (permalink / raw)


On 12/05/2017 09:39 PM, Dmitry A. Kazakov wrote:
> 
> It was your idea not mine.

No, I didn't express my idea. You assume you know what it is, but I suspect 
otherwise. I haven't seriously tried to design a GUI as I think it should be, so 
I may be overlooking some things.

-- 
Jeff Carter
"I did not rob a bank. If I'd robbed a bank, everything
would be great. I tried to rob a bank, is what happened,
and they got me."
Take the Money and Run
139

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

* Re: Full view of a private partial view cannot be a subtype
  2017-12-05 20:59                 ` Randy Brukardt
@ 2017-12-05 22:43                   ` Shark8
  2017-12-07  0:52                     ` Randy Brukardt
  0 siblings, 1 reply; 46+ messages in thread
From: Shark8 @ 2017-12-05 22:43 UTC (permalink / raw)


On Tuesday, December 5, 2017 at 1:59:05 PM UTC-7, Randy Brukardt wrote:
> "Shark8" wrote in message 
> news:43498b2a-773c-454a-b0e7-ade5d6594bd4googlegroups.com...
> ...
> >Besides UIs, the one problem that springs immediately to mind is the 
> >internals of a
> >compiler's IR/parse-tree.
> 
> I can speak to this (at least somewhat), and I think the full OOP version 
> would be a nightmare.

For [only] the Parse-tree/IR?
I honestly don't see why it wouldn't work as a hierarchy, and in fact think it would naturally go that way, especially in an Ada program where you have trees all over the place: the library-hierarchy, nesting of various Ada-elements (package, subprogram, task), etc.

Additionally, there are different extensions that could be made on a particular 'node' -- say the formal generic parameters for a generic.

Here's an interesting tutorial on Pratt Parsing that illustrates the technique (albeit in Java), but while it's on parsing in-general it shows how the elements constructed can be "smart" enough to construct themselves* -- http://journal.stuffwithstuff.com/2011/03/19/pratt-parsers-expression-parsing-made-easy/ 

* Example:
   Type If_Conditional is new Node with record
    Test   : Boolean_Expression;
    Branch : Statement_Sequence;
   end record
    --...
  
   Type If_Else_Conditional is new If_Conditional with record
     Alternative : Statement_Sequence;
   end record
   --...

> 
> Janus/Ada (originally designed in the early 1980s, before there was such a 
> thing as type extension) uses variant records controlled by enumeration 
> discriminants. That is a very effective organization in Ada, because of two 
> features of Ada not found in most other languages - case completeness and 
> variant component checks.

Variant-records are quite good, IMO. There's been several times where working in another OOP-language I've wished I could use Ada due to the case-completeness and/or component-checks. (I view the component checks as merely a special-case/-application of the completeness-checks; the coverage seems like it ought to be "the same" [or at least generalizable like a sort].)

> 
> Thus, I'm unconvinced that a compiler data structure would be any advantage 
> written in OOP (at least, if the "conventional" version was written in Ada). 
> I suspect the reason that OOP held some much advantage to many programmers 
> (read, C programmers) is that they had a language which provided no help at 
> all for "conventional" programming, while Ada already had information 
> hiding, true privacy, case completeness, variant component checks, array 
> index checks, etc. So the increment is so much less.
> 
> I think the only place OOP really holds an advantage is for programs based 
> around call-backs (like most GUIs). And I think you'd be nuts to use 
> call-backs if you don't have to, so there isn't much need for OOP (assuming 
> it is compared to "conventional" Ada and some some other language that lets 
> one do anything, no matter how unintended).

The above example does make use of the "use a classwide object to get around passing a subprogram" trick that was mentioned here on C.L.A a few years back -- http://computer-programming-forum.com/44-ada/30caa21641c1ed2d.htm

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

* Re: Full view of a private partial view cannot be a subtype
  2017-12-05 18:40                 ` Jeffrey R. Carter
@ 2017-12-06 12:54                   ` Jere
  2017-12-06 18:03                     ` Jeffrey R. Carter
  0 siblings, 1 reply; 46+ messages in thread
From: Jere @ 2017-12-06 12:54 UTC (permalink / raw)


On Tuesday, December 5, 2017 at 1:40:40 PM UTC-5, Jeffrey R. Carter wrote:
> 
> But your argument is about ease of writing, with isn't going to convince anyone 
> who likes Ada. Ada explicitly states in the ARM Introduction that it's for code 
> that's easy to read, not easy to write. The fact that you type more with 
> composition is not an argument against it.
No, I wasn't making an argument vs ease of writing.  I was saying that, 
for me, there are cases where composition is harder to read. 

> 
> > I respect yall's view on this, but in either case it is still a subjective
> > matter.  There are a variety of people out there who all view things very
> > differently.
> 
> I disagree. There are a set of S/W-engineering principles that help guide the 
> S/W engineer to create S/W that is simple, correct, and easy to read. Every 
> real-world use of type extension that I've seen has violated the principle of 
> locality--that's inherent in the nature of type extension. Thus it is 
> objectively more complex and harder to read than S/W that violates none of the 
> principles.
> 
I don't think we will ever agree on this topic, because, having grown up as 
someone with trouble reading, I had to find alternate methods to parse 
through what I saw.  It's easy to get overwhelmed when there is so much
to read/go through.  What's readable to you isn't necessarily readable to me.

Hopefully we can just agree to disagree.

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

* Re: Full view of a private partial view cannot be a subtype
  2017-12-06 12:54                   ` Jere
@ 2017-12-06 18:03                     ` Jeffrey R. Carter
  0 siblings, 0 replies; 46+ messages in thread
From: Jeffrey R. Carter @ 2017-12-06 18:03 UTC (permalink / raw)


On 12/06/2017 01:54 PM, Jere wrote:
>>
> I don't think we will ever agree on this topic, because, having grown up as
> someone with trouble reading, I had to find alternate methods to parse
> through what I saw.  It's easy to get overwhelmed when there is so much
> to read/go through.  What's readable to you isn't necessarily readable to me.

S/W is too important for those who are busy creating new buffer-overflow errors 
to be allowed to do it. If we're lucky, that will change. If it does, when we're 
applying for approval, I'd think that a history of violating S/W-engineering 
principles would not be a selling point.

> Hopefully we can just agree to disagree.

Not going to happen. You'll come around to my way of thinking or I shall taunt 
you a second time.

-- 
Jeff Carter
"I fart in your general direction."
Monty Python & the Holy Grail
05

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

* Re: Full view of a private partial view cannot be a subtype
  2017-12-05 21:29                 ` Jeffrey R. Carter
@ 2017-12-07  0:04                   ` Randy Brukardt
  0 siblings, 0 replies; 46+ messages in thread
From: Randy Brukardt @ 2017-12-07  0:04 UTC (permalink / raw)


"Jeffrey R. Carter" <spam.jrcarter.not@spam.not.acm.org> wrote in message 
news:p0733u$b8e$1@dont-email.me...
> On 12/05/2017 09:16 PM, Randy Brukardt wrote:
...
>> Reading the super-secret documentation would help, I hope. ;-)
>
> For the real cases I've experienced recently, I think I read everything 
> available.

A tool like the one we created for Claw probably would be a good thing for 
any Ada program using type extension. (Our tool was cobbled together from 
various existing things without worrying about ease-of-use at all; I can 
barely figure out how to use it, so I don't think it would be a candidate 
for that tool.) No human can figure out what routines are inherited and thus 
available to be called.

                                    Randy.



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

* Re: Full view of a private partial view cannot be a subtype
  2017-12-05 22:43                   ` Shark8
@ 2017-12-07  0:52                     ` Randy Brukardt
  0 siblings, 0 replies; 46+ messages in thread
From: Randy Brukardt @ 2017-12-07  0:52 UTC (permalink / raw)


>"Shark8" <onewingedshark@gmail.com> wrote in message 
>news:f73127a6-2334-430b-80a0-0ac9b9519e89@googlegroups.com...
>On Tuesday, December 5, 2017 at 1:59:05 PM UTC-7, Randy Brukardt wrote:
>> "Shark8" wrote in message
>> news:43498b2a-773c-454a-b0e7-ade5d6594bd4googlegroups.com...
>> ...
>> >Besides UIs, the one problem that springs immediately to mind is the
>> >internals of a
>> >compiler's IR/parse-tree.
>>
>> I can speak to this (at least somewhat), and I think the full OOP version
>> would be a nightmare.
>
>For [only] the Parse-tree/IR?
>I honestly don't see why it wouldn't work as a hierarchy, and in fact think
>it would naturally go that way, especially in an Ada program where you
>have trees all over the place: the library-hierarchy, nesting of various
>Ada-elements (package, subprogram, task), etc.

Of course there is a hierarchy, but that is the least interesting feature of 
"full OOP" as I understand it. (Especially as a variant record is also a 
representation of a hierarchy.) A "full OOP" version has to use dispatching 
operations for essentially all operations on the parse-tree. But there are a 
*lot* of those operations.

Just consider tree walks. Janus/Ada has five primary expression tree walks 
(remember, Janus/Ada doesn't use trees for anything bigger than an 
expression), and a number of secondary ones. These don't all walk the tree 
in the same way, given the different purposes. So one ends up with a whole 
bunch of primitive routines that walk the tree for different purposes and in 
slightly different ways.

When you create a new kind of node (which should be fairly frequent for an 
agile programmers), you have to write bodies for all of these routines. A 
lot of the code of each routine is similar, but sharing that code is hard, 
given that it is interspresed with the other stuff that the tree walk is 
doing. For me (in the Claw Builder), it felt like implementing a lot of 
boilerplate.

Then you have similar things for code generation, serialization (to read 
trees in and out), and so on.

This sort of thing makes agile programming rather difficult (and I thought 
that big-bang programming was mostly dead), as one can't even compile (much 
less test) the new node until all of those routines exist somehow. That took 
a very long time investment for the Claw Builder, and I suspect a real 
compiler would be even worse.

Worse, if you find you need a new kind of tree walk part way through 
development,  you have to add a new kind of dispatching routine to the root 
of the tree, and then add implementations to every node type. That takes 
forever, and is absolutely not agile programming.

Certainly, there are some tools that could help some, but my experience 
suggests that

>Here's an interesting tutorial on Pratt Parsing that illustrates the 
>technique (albeit in
>Java), but while it's on parsing in-general it shows how the elements 
>constructed
>can be "smart" enough to construct themselves*

This is no problem to do (as noted above), the problem is that the result is 
very hard to modify. And if you are building something large and long-lived 
like an Ada compiler, you WILL have to modify it a lot. Maybe Ada 2020 comes 
out, maybe you need to implement a new code generation technique (to improve 
performance or fix a problem with the existing one).

Modifications of OOP designs are inside-out: what usually would be a local 
changes (say a special tree walk to be used in a generic instantiation case) 
tend to have to be done globally (a new dispatching routine has to be added 
to every node), and global changes (like adding a new node) tend to be more 
local. The problem with that is that adding a new node is rather rare (the 
Ada 2012 changes are the first new expression nodes in Janus/Ada since about 
1990), while local fixes to fix bugs are rather common.

You might be able to avoid this problem by abandoning OOP for significant 
parts of the code, but the OOP structure is not then gaining anything about 
extra work to write every dispatching routine.

Someone who has never used variant records in Ada might not realize how 
strong a solution that they actually are to these sorts of problems, and 
thus might think that an OOP solution is the only way to go. But that's not 
really true.

                                          Randy.


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

* Re: Full view of a private partial view cannot be a subtype
  2017-12-05 20:12     ` Randy Brukardt
@ 2017-12-17 15:26       ` Jere
  2017-12-17 15:39         ` Dmitry A. Kazakov
  0 siblings, 1 reply; 46+ messages in thread
From: Jere @ 2017-12-17 15:26 UTC (permalink / raw)


On Tuesday, December 5, 2017 at 3:12:43 PM UTC-5, Randy Brukardt wrote:
> "Jere" wrote in message 
> > On Monday, December 4, 2017 at 3:49:54 PM UTC-5, Randy Brukardt wrote:
> >> "Jere" wrote in message
> >> ...
> >> >   package New_Type1 is
> >> >      subtype Instance is Base.Instance;
> >> >      procedure Operation(Object : in out Instance);
> >> >
> >> >   private
> >> >
> >> >      procedure Operation(Object : in out Instance) renames 
> >> > Base.Operation;
> >> >   end New_Type1;
> >> >
> >> > (NOTE:  is there a better way to do this?)
> >>
> >> No, no better way yet, but maybe (large maybe here) in Ada 2020. (I'm
> >> leaving out all details because none have been determined yet and perhaps
> >> never will be for Ada 2020.)
> >
> > Sounds intriguing!
> >
> >>
> >> > This is all well and good, but sometimes while I as an implementer
> >> > want this kind of relationship, I don't necessarily want to expose
> >> > that relationship outside the private section of a package.  Here I
> >> > run into a problem as I cannot (as far as I can tell) do:
> >> >
> >> >   package New_Type2 is
> >> >      type Instance is tagged limited private;
> >> >      procedure Operation(Object : in out Instance);
> >> >   private
> >> >      subtype Instance is Base.Instance;
> >>
> >> This is illegal; a private type has to be completed with a full type, not 
> >> a
> >> subtype. (If you have a compiler that is allowing this, it is 
> >> confused...)
> >
> > Yep, that was my comment.  Basically I have a low level package that is 
> > used
> > to create many higher level, more client friendly packages:
> >
> > generic
> >   type Input_Type(<>);
> >   with procedure Really_Dangerous_To_Call(Object : Input_Type);
> >   Value : Integer;
> > package Low_Level_Package
> >
> >   type My_Type is private;
> >   type Numeric_Type is <some implementation using Value>;
> >
> >   function Client_Friendly_Procedure
> >     (Object : My_Type)
> >      return Numeric_Type;
> >
> >   <other operations>
> >
> > private
> >   ...
> >
> > end Low_Level_Package;
> >
> > and I want to use it to make some more client friendly versions.
> > The procedure, Really_Dangerous_To_Call, isn't meant to be called
> > directly for a client.  It is meant to be used to setup implementations
> > behind the client packages.
> 
> If you control the entire design of the type hierarchy, the best way to do 
> this is to put "Really_Dangerous_to_Call" into the private part of the root 
> operation, and declare the child types in child packages. Then, the child 
> types can call the routine but clients cannot. (An added advantage is that 
> Really_Dangerous_to_Call can be dispatching in such a design.)
> 
> <SNIPPED Claw example>
>                                       Randy.
Thanks!

I think that still leaves me with the same issue.  All I really want out
of the client package is that it implements subtypes and renames of the
hidden package.  I don't really want to derive or extend or even do
composition if I have to because it leads to a lot of code that is easy
to mistype, difficult to parse through and read later on, and possibly add 
overhead (not normally an issue, but this is a low level core library
for me so I at least have to consider my implementation some).  All for
no readability benefit (and actual detriment to reading).

my assertion is that:

   subtype Thing is Core_Pkg.Thing;

   procedure Do_Something(The_Thing : in out Thing)
      renames Core_Pkg.Do_Something;
       

is easier to both maintain and read than:

   type Thing is new Core_Pkg.Thing with null record;
   
   procedure Do_Something(The_Thing : in out Thing);

   ...

   procedure Do_Something(The_Thing : in out Thing) is
   begin
      Core_Pkg.Thing(The_Thing).Do_Something;
   end Do_Something;

and:

   type Thing is record
      Parent_Thing : Core_Pkg.Thing;
   end record;

   procedure Do_Something(The_Thing : in out Thing);

   ...

   procedure Do_Something(The_Thing : in out Thing) is
   begin
      The_Thing.Parent_Thing.Do_Something;
   end Do_Something;

The first option completely conveys how I want to implement it while
the latter two options require additional code that adds no extra
readability and gives the reader/maintainer even more to parse through
(additional files and additional code) in order to determine what is
going on.  Furthermore it opens the maintainer up to more mistakes if
this needs to be done for a lot of functions (20+).  Additionally, the
complexity in both reading and maintainability only gets worse if the
operation signatures use multiple types that all need this same treatment.

I don't mind writing the extra stuff if it gives me more readability or
safety, but in this case it just feels like I am trading up readability
for more writing, which I don't like doing.  I like things easy to read.

You're correct in that using private packages hides the
Really_Dangerous_To_Call uses, but I'm still left with the original
issue that I am making my code more unreadable to do so.  I know that, 
based on this email chain, the latter two are my only options.  I was
just hoping there was a third option involving encapsulation of subtypes.

Out of the two later approaches, composition fairs much better in
readability (and possible overhead).  It just has much less readability
than the subtype method.

I can try to give better specifics if that helps.  I try to avoid that in
C.L.A though as it ends up sending people down paths that are tangential,
and my original question gets lost.  Also it helps to keep things simple
so that people can more easily help/answer.  I realize the onus is on me 
to be better at explaining what I need though.  So if you need better
specifics, I can do better to provide them.

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

* Re: Full view of a private partial view cannot be a subtype
  2017-12-17 15:26       ` Jere
@ 2017-12-17 15:39         ` Dmitry A. Kazakov
  2017-12-18 22:47           ` Randy Brukardt
  2017-12-19  1:01           ` Jere
  0 siblings, 2 replies; 46+ messages in thread
From: Dmitry A. Kazakov @ 2017-12-17 15:39 UTC (permalink / raw)


On 2017-12-17 16:26, Jere wrote:

> my assertion is that:
> 
>     subtype Thing is Core_Pkg.Thing;
> 
>     procedure Do_Something(The_Thing : in out Thing)
>        renames Core_Pkg.Do_Something;
>         
> 
> is easier to both maintain and read than:
> 
>     type Thing is new Core_Pkg.Thing with null record;
>     
>     procedure Do_Something(The_Thing : in out Thing);

But these are two semantically different concepts. Ada's subtype 
declares an equivalent type [it inherits everything from and exports 
everything to the base]. Ada's new tagged type declares a new instance 
of a class. It only inherits.

I don't understand how can you exchange one for another.

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


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

* Re: Full view of a private partial view cannot be a subtype
  2017-12-03  2:14 Full view of a private partial view cannot be a subtype Jere
  2017-12-03 12:01 ` Jeffrey R. Carter
  2017-12-04 20:49 ` Randy Brukardt
@ 2017-12-18 20:45 ` Stephen Leake
  2017-12-18 22:54   ` Randy Brukardt
  2017-12-19  1:08   ` Jere
  2 siblings, 2 replies; 46+ messages in thread
From: Stephen Leake @ 2017-12-18 20:45 UTC (permalink / raw)


On Saturday, December 2, 2017 at 8:14:50 PM UTC-6, Jere wrote:
> There are times where in another package I want to
> subtype Base.Instance and do renames of the operations in order
> to bring them all into scope (or whatever the correct term is):
> 
>    package New_Type1 is
>       subtype Instance is Base.Instance;
>       procedure Operation(Object : in out Instance);
>       
>    private
>       
>       procedure Operation(Object : in out Instance) renames Base.Operation;
>    end New_Type1;

Why subtype? why not a derived type? why do you need a new name with the same operations?

> (NOTE:  is there a better way to do this?)

Yes, use a derived type:

type Instance is new Base.Instance;

Since Base.Instance is not abstract, you don't need to do anything else; all the operations are inherited.

Optionally, you can override some operations to change what they do.

> So I guess my question is two part:
> 
> 1.  Is there a way to make the full view of a private type
>     a subtype when the partial view is not a subtype? Or am
>     I forced to derive a new type?
> 
> 2.  If it isn't possible, are there any language reasons for
>     why that must be so?  Would making a full view of a type
>     actually a subtype under the hood break something?

subtypes just declare a new name with new constraints; derived types declare a new type. So you'd be lying to the clients of the package; that always causes problems.

-- Stephe


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

* Re: Full view of a private partial view cannot be a subtype
  2017-12-17 15:39         ` Dmitry A. Kazakov
@ 2017-12-18 22:47           ` Randy Brukardt
  2017-12-19  1:22             ` Jere
  2017-12-19  1:01           ` Jere
  1 sibling, 1 reply; 46+ messages in thread
From: Randy Brukardt @ 2017-12-18 22:47 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:p16332$1rfb$1@gioia.aioe.org...
> On 2017-12-17 16:26, Jere wrote:
>
>> my assertion is that:
>>
>>     subtype Thing is Core_Pkg.Thing;
>>
>>     procedure Do_Something(The_Thing : in out Thing)
>>        renames Core_Pkg.Do_Something;
>>         is easier to both maintain and read than:
>>
>>     type Thing is new Core_Pkg.Thing with null record;
>>     procedure Do_Something(The_Thing : in out Thing);
>
> But these are two semantically different concepts. Ada's subtype declares 
> an equivalent type [it inherits everything from and exports everything to 
> the base]. Ada's new tagged type declares a new instance of a class. It 
> only inherits.
>
> I don't understand how can you exchange one for another.

You can't really; they're very different concepts. The OP is showing a 
confusion, because the renames he wants is perfectly legal, assuming proper 
visibility. And if the items in question are private, then he is trying to 
make a privacy leak -- which the language will not make easy for obvious 
reasons.

                            Randy/


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

* Re: Full view of a private partial view cannot be a subtype
  2017-12-18 20:45 ` Stephen Leake
@ 2017-12-18 22:54   ` Randy Brukardt
  2017-12-19  1:08   ` Jere
  1 sibling, 0 replies; 46+ messages in thread
From: Randy Brukardt @ 2017-12-18 22:54 UTC (permalink / raw)


"Stephen Leake" <stephen_leake@stephe-leake.org> wrote in message 
news:ceef5c1e-b80b-42c7-9d11-12e52dc6c266@googlegroups.com...
> On Saturday, December 2, 2017 at 8:14:50 PM UTC-6, Jere wrote:
>> There are times where in another package I want to
>> subtype Base.Instance and do renames of the operations in order
>> to bring them all into scope (or whatever the correct term is):
>>
>>    package New_Type1 is
>>       subtype Instance is Base.Instance;
>>       procedure Operation(Object : in out Instance);
>>
>>    private
>>
>>       procedure Operation(Object : in out Instance) renames 
>> Base.Operation;
>>    end New_Type1;
>
> Why subtype? why not a derived type? why do you need a new name with the 
> same operations?
>
>> (NOTE:  is there a better way to do this?)
>
> Yes, use a derived type:
>
> type Instance is new Base.Instance;
>
> Since Base.Instance is not abstract, you don't need to do anything else; 
> all the operations are inherited.
>
> Optionally, you can override some operations to change what they do.
>
>> So I guess my question is two part:
>>
>> 1.  Is there a way to make the full view of a private type
>>     a subtype when the partial view is not a subtype? Or am
>>     I forced to derive a new type?
>>
>> 2.  If it isn't possible, are there any language reasons for
>>     why that must be so?  Would making a full view of a type
>>     actually a subtype under the hood break something?
>
> subtypes just declare a new name with new constraints; derived types
> declare a new type. So you'd be lying to the clients of the package;
> that always causes problems.

Right.

The type model of Ada is that every named type is disjoint. For the 
perspective of a client, a private type is different  than any other type 
that it could know about. OTOH, a subtype is the *same* type as some other 
type. So you would have view-dependent typing (depending on where you are in 
the program, it would differ as to whether whether the types are distinct or 
the same). We have a saying for such thing in the ARG: "that way lies 
madness!".

The only other way to make it work would be to abandon strict privacy, and 
have the semantics of a private type depend on the completion. That would be 
totally contrary to the goals of Ada, so that's not a serious option, 
either.

So this is not happening, it does not make semantic sense.

                                     Randy.




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

* Re: Full view of a private partial view cannot be a subtype
  2017-12-17 15:39         ` Dmitry A. Kazakov
  2017-12-18 22:47           ` Randy Brukardt
@ 2017-12-19  1:01           ` Jere
  2017-12-19  9:08             ` Dmitry A. Kazakov
  2017-12-19 19:10             ` Stephen Leake
  1 sibling, 2 replies; 46+ messages in thread
From: Jere @ 2017-12-19  1:01 UTC (permalink / raw)


On Sunday, December 17, 2017 at 10:39:17 AM UTC-5, Dmitry A. Kazakov wrote:
> On 2017-12-17 16:26, Jere wrote:
> 
> > my assertion is that:
> > 
> >     subtype Thing is Core_Pkg.Thing;
> > 
> >     procedure Do_Something(The_Thing : in out Thing)
> >        renames Core_Pkg.Do_Something;
> >         
> > 
> > is easier to both maintain and read than:
> > 
> >     type Thing is new Core_Pkg.Thing with null record;
> >     
> >     procedure Do_Something(The_Thing : in out Thing);
> 
> But these are two semantically different concepts. Ada's subtype 
> declares an equivalent type [it inherits everything from and exports 
> everything to the base]. Ada's new tagged type declares a new instance 
> of a class. It only inherits.
> 
> I don't understand how can you exchange one for another.
> 
> -- 
> Regards,
> Dmitry A. Kazakov
> http://www.dmitry-kazakov.de

I don't want to exchange one for the other.  I have a package that I want
to provide default arguments to privately but maintain the same exact 
type/operation specification.  Subtyping seems more correct than
inheritance in this case.  I'm not trying to define a new type or an
extension of a type.  I just want provide a simpler interface to a
much more complex generic while hiding part of that so the user doesn't
accidentally do something they shouldn't. 

Something like:

generic
   type Item_Type(<>);
   type Item_Access is access Item_type;
   with procedure Deallocation(Ref : in out Item_Access);
package Sledgehammer is
   <types>
   <operations>
private
   <implementation>
end Sledgehammer;

This would be used in maybe 5% or less of the code base and only
when absolutely necessary.  I want to convert it to:

generic
   type Item_Type(<>) is limited private;
package Nicer_Package is
   type Item_Access is access Item_Type;
   <same types>
   <same operations>
private
   procedure Deallocate is new Ada.Unchecked_Deallocation
      (Item_Type,Item_Access);

   package Implementation is new Sledgehammer
      (Item_Type => Item_Type,
       Item_Access => Item_Access,
       Deallocation => Deallocate);

   <implementation>
end Nicer_Package;

Since all I am doing is automating the access type and
the deallocation operation, I don't think a new type
is really the right design. Additionally, I don't want
to expose the deallocation operation as it should never
be called directly.

Based on earlier conversion from Jeff, it looks like
composition is my best bet since I cannot do it via
subtyping and renames.  I was just hoping there was a
way I could do it without adding so much extra stuff
to read and maintain.  I don't like decreasing 
readability like that.  If I am willing to expose the
deallocation operation, then I can just use subtype
and renames (which make more sense to me in this
case) but that's the tradeoff. 

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

* Re: Full view of a private partial view cannot be a subtype
  2017-12-18 20:45 ` Stephen Leake
  2017-12-18 22:54   ` Randy Brukardt
@ 2017-12-19  1:08   ` Jere
  1 sibling, 0 replies; 46+ messages in thread
From: Jere @ 2017-12-19  1:08 UTC (permalink / raw)


On Monday, December 18, 2017 at 3:45:31 PM UTC-5, Stephen Leake wrote:
> On Saturday, December 2, 2017 at 8:14:50 PM UTC-6, Jere wrote:
> > There are times where in another package I want to
> > subtype Base.Instance and do renames of the operations in order
> > to bring them all into scope (or whatever the correct term is):
> > 
> >    package New_Type1 is
> >       subtype Instance is Base.Instance;
> >       procedure Operation(Object : in out Instance);
> >       
> >    private
> >       
> >       procedure Operation(Object : in out Instance) renames Base.Operation;
> >    end New_Type1;
> 
> Why subtype? why not a derived type? why do you need a new name with the same operations?

It's not a new name...it's actually the same name in a different package.  I
am basically trying to mimic a much more complex package with a simpler one.
They would have the same typenames and operations.  I didn't really want to
create a new type, just provide a simpler interface to an existing one while
hiding one particularly dangerous detail if I could.

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

* Re: Full view of a private partial view cannot be a subtype
  2017-12-18 22:47           ` Randy Brukardt
@ 2017-12-19  1:22             ` Jere
  2017-12-19 23:16               ` Randy Brukardt
  0 siblings, 1 reply; 46+ messages in thread
From: Jere @ 2017-12-19  1:22 UTC (permalink / raw)


On Monday, December 18, 2017 at 5:47:51 PM UTC-5, Randy Brukardt wrote:
> "Dmitry A. Kazakov" wrote in message 
> > On 2017-12-17 16:26, Jere wrote:
> >
> >> my assertion is that:
> >>
> >>     subtype Thing is Core_Pkg.Thing;
> >>
> >>     procedure Do_Something(The_Thing : in out Thing)
> >>        renames Core_Pkg.Do_Something;
> >>         is easier to both maintain and read than:
> >>
> >>     type Thing is new Core_Pkg.Thing with null record;
> >>     procedure Do_Something(The_Thing : in out Thing);
> >
> > But these are two semantically different concepts. Ada's subtype declares 
> > an equivalent type [it inherits everything from and exports everything to 
> > the base]. Ada's new tagged type declares a new instance of a class. It 
> > only inherits.
> >
> > I don't understand how can you exchange one for another.
> 
> You can't really; they're very different concepts. The OP is showing a 
> confusion, because the renames he wants is perfectly legal, assuming proper 
> visibility. And if the items in question are private, then he is trying to 
> make a privacy leak -- which the language will not make easy for obvious 
> reasons.
> 
>                             Randy/

I'm not really trying to make a privacy leak on purpose.  I'm just trying to
provide a simpler interface to a much more complex and dangerous generic
so that someone doesn't accidentally use something they shouldn't.  Any 
privacy leaks are not intentional.  I was just asking a question.  Using
either extension, derivations, or composition all seemed very heavy handed
for just wanting to mimic the same specification as another generic.  Subtypes
and renames expressed exactly the relationship I wanted, but the only thing
I couldn't do was hide a deallocation operation that should never be called
directly (it was an input to the base generic).  That one items is what 
got me to this question.  I wanted to see if there was a way to keep the
subtype/rename method while hiding the operation and the answer looks to be
no.  But I wasn't sitting around twiddling my fingers looking for ways to
break Ada privacy in the process.  I just wanted to understand if there was
a way and if not, why.  That's all, nothing nefarious on my part, at least
not intentionally.


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

* Re: Full view of a private partial view cannot be a subtype
  2017-12-19  1:01           ` Jere
@ 2017-12-19  9:08             ` Dmitry A. Kazakov
  2017-12-19 13:08               ` Jere
  2017-12-19 19:10             ` Stephen Leake
  1 sibling, 1 reply; 46+ messages in thread
From: Dmitry A. Kazakov @ 2017-12-19  9:08 UTC (permalink / raw)


On 2017-12-19 02:01, Jere wrote:
> On Sunday, December 17, 2017 at 10:39:17 AM UTC-5, Dmitry A. Kazakov wrote:
>> On 2017-12-17 16:26, Jere wrote:
>>
> Something like:
> 
> generic
>     type Item_Type(<>);
>     type Item_Access is access Item_type;
>     with procedure Deallocation(Ref : in out Item_Access);
> package Sledgehammer is
>     <types>
>     <operations>
> private
>     <implementation>
> end Sledgehammer;
> 
> This would be used in maybe 5% or less of the code base and only
> when absolutely necessary.  I want to convert it to:
> 
> generic
>     type Item_Type(<>) is limited private;
> package Nicer_Package is
>     type Item_Access is access Item_Type;
>     <same types>
>     <same operations>
> private
>     procedure Deallocate is new Ada.Unchecked_Deallocation
>        (Item_Type,Item_Access);
> 
>     package Implementation is new Sledgehammer
>        (Item_Type => Item_Type,
>         Item_Access => Item_Access,
>         Deallocation => Deallocate);
> 
>     <implementation>
> end Nicer_Package;
> 
> Since all I am doing is automating the access type and
> the deallocation operation, I don't think a new type
> is really the right design. Additionally, I don't want
> to expose the deallocation operation as it should never
> be called directly.

How do you create objects?

There are two approaches:

1. Explicit new, implicit deallocate. This works only with containers, 
which should know the access type and the deallocator.

2. Factory (a Create call), implicit deallocate. This requires reference 
counting or custom GC pool.

P.S., declaring an access type in the public part of a generic is 
suspicious for bad design.

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


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

* Re: Full view of a private partial view cannot be a subtype
  2017-12-19  9:08             ` Dmitry A. Kazakov
@ 2017-12-19 13:08               ` Jere
  2017-12-19 13:27                 ` Dmitry A. Kazakov
  0 siblings, 1 reply; 46+ messages in thread
From: Jere @ 2017-12-19 13:08 UTC (permalink / raw)


On Tuesday, December 19, 2017 at 4:08:46 AM UTC-5, Dmitry A. Kazakov wrote:
> On 2017-12-19 02:01, Jere wrote:
> > On Sunday, December 17, 2017 at 10:39:17 AM UTC-5, Dmitry A. Kazakov wrote:
> >> On 2017-12-17 16:26, Jere wrote:
> >>
> > Something like:
> > 
> > generic
> >     type Item_Type(<>);
> >     type Item_Access is access Item_type;
> >     with procedure Deallocation(Ref : in out Item_Access);
> > package Sledgehammer is
> >     <types>
> >     <operations>
> > private
> >     <implementation>
> > end Sledgehammer;
> > 
> > This would be used in maybe 5% or less of the code base and only
> > when absolutely necessary.  I want to convert it to:
> > 
> > generic
> >     type Item_Type(<>) is limited private;
> > package Nicer_Package is
> >     type Item_Access is access Item_Type;
> >     <same types>
> >     <same operations>
> > private
> >     procedure Deallocate is new Ada.Unchecked_Deallocation
> >        (Item_Type,Item_Access);
> > 
> >     package Implementation is new Sledgehammer
> >        (Item_Type => Item_Type,
> >         Item_Access => Item_Access,
> >         Deallocation => Deallocate);
> > 
> >     <implementation>
> > end Nicer_Package;
> > 
> > Since all I am doing is automating the access type and
> > the deallocation operation, I don't think a new type
> > is really the right design. Additionally, I don't want
> > to expose the deallocation operation as it should never
> > be called directly.
> 
> How do you create objects?

Explicit.  The client does.  It's mostly due to the need
for of the incomplete type.  I can't make or manage objects
of type Item_Type, so the client has to allocate.

> 
> There are two approaches:
> 
> 1. Explicit new, implicit deallocate. This works only with containers, 
> which should know the access type and the deallocator.
> 
> 2. Factory (a Create call), implicit deallocate. This requires reference 
> counting or custom GC pool.
> 
> P.S., declaring an access type in the public part of a generic is 
> suspicious for bad design.
> 
Again, it is only for basically to keep the client from having to
specify in 90-95% of the situations where they don't really need it.
The type is never used to create variables.  In the more complex
generic, I make the client specify instead, but the simpler one is
just for quick utility and hopefully lack of exposure to the deallocation
routine.


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

* Re: Full view of a private partial view cannot be a subtype
  2017-12-19 13:08               ` Jere
@ 2017-12-19 13:27                 ` Dmitry A. Kazakov
  0 siblings, 0 replies; 46+ messages in thread
From: Dmitry A. Kazakov @ 2017-12-19 13:27 UTC (permalink / raw)


On 2017-12-19 14:08, Jere wrote:

>> How do you create objects?
> 
> Explicit.  The client does.  It's mostly due to the need
> for of the incomplete type.  I can't make or manage objects
> of type Item_Type, so the client has to allocate.

How do you deallocate it?

I usually use reference counting. The clients use a handle type which is 
controlled. The handle references a limited controlled type. Ideally the 
clients do not see the target type and use handles only.

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


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

* Re: Full view of a private partial view cannot be a subtype
  2017-12-19  1:01           ` Jere
  2017-12-19  9:08             ` Dmitry A. Kazakov
@ 2017-12-19 19:10             ` Stephen Leake
  1 sibling, 0 replies; 46+ messages in thread
From: Stephen Leake @ 2017-12-19 19:10 UTC (permalink / raw)


On Monday, December 18, 2017 at 7:01:49 PM UTC-6, Jere wrote:
> On Sunday, December 17, 2017 at 10:39:17 AM UTC-5, Dmitry A. Kazakov wrote:
> > On 2017-12-17 16:26, Jere wrote:
> > 
> > > my assertion is that:
> > > 
> > >     subtype Thing is Core_Pkg.Thing;
> > > 
> > >     procedure Do_Something(The_Thing : in out Thing)
> > >        renames Core_Pkg.Do_Something;
> > >         
> > > 
> > > is easier to both maintain and read than:
> > > 
> > >     type Thing is new Core_Pkg.Thing with null record;
> > >     
> > >     procedure Do_Something(The_Thing : in out Thing);
> > 
> > But these are two semantically different concepts. Ada's subtype 
> > declares an equivalent type [it inherits everything from and exports 
> > everything to the base]. Ada's new tagged type declares a new instance 
> > of a class. It only inherits.
> > 
> > I don't understand how can you exchange one for another.
> > 
> > -- 
> > Regards,
> > Dmitry A. Kazakov
> > http://www.dmitry-kazakov.de
> 
> I don't want to exchange one for the other.  I have a package that I want
> to provide default arguments to privately but maintain the same exact 
> type/operation specification.  Subtyping seems more correct than
> inheritance in this case.  I'm not trying to define a new type or an
> extension of a type.  I just want provide a simpler interface to a
> much more complex generic while hiding part of that so the user doesn't
> accidentally do something they shouldn't. 
> 
> Something like:
> 
> generic
>    type Item_Type(<>);
>    type Item_Access is access Item_type;
>    with procedure Deallocation(Ref : in out Item_Access);
> package Sledgehammer is
>    <types>
>    <operations>
> private
>    <implementation>
> end Sledgehammer;
> 
> This would be used in maybe 5% or less of the code base and only
> when absolutely necessary.  I want to convert it to:
> 
> generic
>    type Item_Type(<>) is limited private;
> package Nicer_Package is
>    type Item_Access is access Item_Type;
>    <same types>
>    <same operations>
> private
>    procedure Deallocate is new Ada.Unchecked_Deallocation
>       (Item_Type,Item_Access);
> 
>    package Implementation is new Sledgehammer
>       (Item_Type => Item_Type,
>        Item_Access => Item_Access,
>        Deallocation => Deallocate);
> 
>    <implementation>
> end Nicer_Package;

I had a pattern like that in my original SAL library. I provided "Aux" generics to do the helper instantiations in the simple cases, so the typical use case was:

package My_List_Aux is new Sledgehammer_Aux (Item_Type);
package My_Lists is new Sledgehammer (Item_Type, My_List_Aux.Item_Access, My_List_Aux.Deallocate);

I found that to be a good compromise.

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

* Re: Full view of a private partial view cannot be a subtype
  2017-12-19  1:22             ` Jere
@ 2017-12-19 23:16               ` Randy Brukardt
  0 siblings, 0 replies; 46+ messages in thread
From: Randy Brukardt @ 2017-12-19 23:16 UTC (permalink / raw)


"Jere" <jhb.chat@gmail.com> wrote in message 
news:c29c753e-18e9-475b-9a28-a19aa697ea2f@googlegroups.com...
...
> Using
> either extension, derivations, or composition all seemed very heavy handed
> for just wanting to mimic the same specification as another generic.

Fair enough, but it seems like a bizarre thing to do. If I start getting a 
generic design that is too complex to use easily, I'm likely to toss the 
entire thing in the junk and do something else. (And exposing access types 
is almost always a bad idea, because you force the client to do memory 
management, eliminating the possibilities that they have of using containers 
or stack allocation to avoid it altogether.)

Also note that you'll end up with visibility problems if both packages end 
up used in a program (which seems likely), as the operations in each will 
conflict.

                  Randy.



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

end of thread, other threads:[~2017-12-19 23:16 UTC | newest]

Thread overview: 46+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-12-03  2:14 Full view of a private partial view cannot be a subtype Jere
2017-12-03 12:01 ` Jeffrey R. Carter
2017-12-03 13:33   ` Jere
2017-12-03 14:34     ` Jeffrey R. Carter
2017-12-03 17:44       ` Robert Eachus
2017-12-03 18:50         ` Simon Wright
2017-12-03 22:10           ` Robert Eachus
2017-12-03 19:03         ` Jeffrey R. Carter
2017-12-03 22:23       ` Jere
2017-12-04  8:25         ` Dmitry A. Kazakov
2017-12-04 18:04         ` Jeffrey R. Carter
2017-12-04 20:41           ` Jere
2017-12-04 21:48             ` Jeffrey R. Carter
2017-12-05  8:20               ` Dmitry A. Kazakov
2017-12-05 18:16                 ` Jeffrey R. Carter
2017-12-05 20:39                   ` Dmitry A. Kazakov
2017-12-05 21:38                     ` Jeffrey R. Carter
2017-12-05 12:35               ` Jere
2017-12-05 18:40                 ` Jeffrey R. Carter
2017-12-06 12:54                   ` Jere
2017-12-06 18:03                     ` Jeffrey R. Carter
2017-12-05 20:22                 ` Randy Brukardt
2017-12-05 15:27               ` Shark8
2017-12-05 18:50                 ` Jeffrey R. Carter
2017-12-05 20:59                 ` Randy Brukardt
2017-12-05 22:43                   ` Shark8
2017-12-07  0:52                     ` Randy Brukardt
2017-12-05 20:16               ` Randy Brukardt
2017-12-05 21:29                 ` Jeffrey R. Carter
2017-12-07  0:04                   ` Randy Brukardt
2017-12-04 20:49 ` Randy Brukardt
2017-12-05 12:56   ` Jere
2017-12-05 20:12     ` Randy Brukardt
2017-12-17 15:26       ` Jere
2017-12-17 15:39         ` Dmitry A. Kazakov
2017-12-18 22:47           ` Randy Brukardt
2017-12-19  1:22             ` Jere
2017-12-19 23:16               ` Randy Brukardt
2017-12-19  1:01           ` Jere
2017-12-19  9:08             ` Dmitry A. Kazakov
2017-12-19 13:08               ` Jere
2017-12-19 13:27                 ` Dmitry A. Kazakov
2017-12-19 19:10             ` Stephen Leake
2017-12-18 20:45 ` Stephen Leake
2017-12-18 22:54   ` Randy Brukardt
2017-12-19  1:08   ` Jere

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