comp.lang.ada
 help / color / mirror / Atom feed
* Extending a third party tagged type while adding finalization
@ 2017-11-22 12:43 Jere
  2017-11-22 16:42 ` AdaMagica
  0 siblings, 1 reply; 45+ messages in thread
From: Jere @ 2017-11-22 12:43 UTC (permalink / raw)


Has anyone have any good tips for extending a third party type:

type Third_Party_Type is tagged private;

I want to extend it but also add finalization which is inheritable
by later descendants:

type My_Base_Type is new Third_Party_Type with private;
procedure Finalize(Object : in out My_Type);
procedure Initialize(Object : in out My_Type);
procedure Adjust(Object : in out My_Type);

That way, clients of My_Base_Type can use them along side Third_Party_Type such
as through a variable of Third_Party_Type'Class.  My first (untested) thought
is to maybe string together a proxy object inside My_Base_Type using the
Rosen technique and have it forward the Finalization operations through 
dispatch.  I haven't tested this to see if it works but even if it does, it
feels very hacky and is not my preferred way.

Does anyone have any techniques they have used in the past?  

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

* Re: Extending a third party tagged type while adding finalization
  2017-11-22 12:43 Extending a third party tagged type while adding finalization Jere
@ 2017-11-22 16:42 ` AdaMagica
  2017-11-26 17:33   ` Jere
  0 siblings, 1 reply; 45+ messages in thread
From: AdaMagica @ 2017-11-22 16:42 UTC (permalink / raw)


Perhaps this might help you:

http://www.christ-usch-grein.homepage.t-online.de/Ada/Finalization.html

I published this in Ada Letters, Volume XIX, Number 4, December 1999.


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

* Re: Extending a third party tagged type while adding finalization
  2017-11-22 16:42 ` AdaMagica
@ 2017-11-26 17:33   ` Jere
  2017-11-26 18:15     ` Dmitry A. Kazakov
                       ` (2 more replies)
  0 siblings, 3 replies; 45+ messages in thread
From: Jere @ 2017-11-26 17:33 UTC (permalink / raw)


On Wednesday, November 22, 2017 at 11:42:19 AM UTC-5, AdaMagica wrote:
> Perhaps this might help you:
> 
> http://www.christ-usch-grein.homepage.t-online.de/Ada/Finalization.html
> 
> I published this in Ada Letters, Volume XIX, Number 4, December 1999.

That's similar to what I tried.  The only things it didn't cover that 
my attempt did was 1.)  allowing extension on the Finalize  2.) The 
same for Initialize.

What I tried to do was use a mixin but have it keep a reference to a
classwide access on the object.  Then I tried dispatching out to the
correct object type from there.  This kind of highlighted the evils
of using redispatch in Ada though as I found that if I had component
definitions like this:

**********************************************************************

   package Components is
      type LC_Component1 is 
         new Ada.Finalization.Limited_Controlled 
      with null record;
      overriding procedure Initialize(Self : in out LC_Component1);
      overriding procedure Finalize(Self : in out LC_Component1);
      
      type LC_Component2 is 
         new Ada.Finalization.Limited_Controlled 
      with null record;
      overriding procedure Initialize(Self : in out LC_Component2);
      overriding procedure Finalize(Self : in out LC_Component2);
   end Components;
   
   package body Components is
      overriding procedure Initialize(Self : in out LC_Component1) is
      begin
         Put_Line("LC1: Initialize");
      end Initialize;
      
      overriding procedure Finalize(Self : in out LC_Component1) is
      begin
         Put_Line("LC1: Finalize");
      end Finalize;
      
      overriding procedure Initialize(Self : in out LC_Component2) is
      begin
         Put_Line("LC2: Initialize");
      end Initialize;
      
      overriding procedure Finalize(Self : in out LC_Component2) is
      begin
         Put_Line("LC2: Finalize");
      end Finalize;
   end Components; 

**********************************************************************

And I had it so some uncontrolled base type had a component of LC1 while
a descendant of my mixin had a component of LC2:

**********************************************************************

   package Base is
      type Instance is tagged limited record
         c1 : Components.LC_Component1;
      end record;
   end Base;
   
   package LC is new Bullfrog.Limited_Controlled_Mixin(Base.Instance);
   
   package Extension is
      type Instance is new LC.Limited_Controlled with record
         c2 : Components.LC_Component2;
      end record;
      
      overriding procedure Initialize(Self : in out Instance);
      overriding procedure Finalize(Self : in out Instance);
   end Extension;
   
   package body Extension is
      overriding procedure Initialize(Self : in out Instance) is
      begin
         Put_Line("Extension: Initialize");
      end Initialize;
      
      overriding procedure Finalize(Self : in out Instance) is
      begin
         Put_Line("Extension: Finalize");
      end Finalize;
   end Extension;

**********************************************************************

Then the component c2 would Initialize too late for my solution and it
would finalize too early.  Output from my test by simply declaring a
variable of type Extension.Instance:

Starting Test_Limited_Controlled_Mixin
LC1: Initialize
Extension: Initialize
LC2: Initialize
LC2: Finalize
Extension: Finalize
LC1: Finalize

So while it is safe to add in the Initialize and Finalize functionality,
it isn't safe to do so and also have the ability to make it inheritable
for descendants.  I'm guessing there may not be a safe way to do it so
it'll just have to fall on the descendant to wrap their components in
a Finalization type.

Based on what I have read so far, I didn't see any discussion that would
lead me to think this will be changed at least in the near future.  I
wish there was a way it would be easy for vendors to do something like:

type Some_Type is tagged private;
for Some_Type'Initialize use Initialize_Some_Type;
for Some_Type'Adjust use Adjust_Some_Type;
for Some_Type'Finalize use Finalize_Some_Type;

and then just have the compiler handle adding the needed structures
to the type under the hood (like how GNAT uses Controlled to hold
a linked list under the hood...but compiler managed).

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

* Re: Extending a third party tagged type while adding finalization
  2017-11-26 17:33   ` Jere
@ 2017-11-26 18:15     ` Dmitry A. Kazakov
  2017-11-26 19:31       ` Jere
  2017-11-27  9:46     ` AdaMagica
  2017-11-27 18:10     ` Shark8
  2 siblings, 1 reply; 45+ messages in thread
From: Dmitry A. Kazakov @ 2017-11-26 18:15 UTC (permalink / raw)


On 2017-11-26 18:33, Jere wrote:

> Based on what I have read so far, I didn't see any discussion that would
> lead me to think this will be changed at least in the near future.

It was discussed on many occasions here in c.l.a.

The bottom line is - Ada does not have proper user-defined 
constructors/destructors and will have none in any observable future.

> I wish there was a way it would be easy for vendors to do something like:
> 
> type Some_Type is tagged private;

You must always use the Ada.Finalization hack on the parent type. There 
is no other way safe, and Ada.Finalization is not very safe either when 
inheritance, task components, or Rosen's trick components are involved.

Making controlled components responsible for container's 
initialization/finalization is inherently unsafe because these will be 
done in wrong order. The reason is same why any components with Rosen's 
trick are unsafe. For them there is no right order at all, they must be 
handled twice at two different stages of initialization/finalization.

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


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

* Re: Extending a third party tagged type while adding finalization
  2017-11-26 18:15     ` Dmitry A. Kazakov
@ 2017-11-26 19:31       ` Jere
  0 siblings, 0 replies; 45+ messages in thread
From: Jere @ 2017-11-26 19:31 UTC (permalink / raw)


On Sunday, November 26, 2017 at 1:15:53 PM UTC-5, Dmitry A. Kazakov wrote:
> On 2017-11-26 18:33, Jere wrote:
> 
> > Based on what I have read so far, I didn't see any discussion that would
> > lead me to think this will be changed at least in the near future.
> 
> It was discussed on many occasions here in c.l.a.
> 
> The bottom line is - Ada does not have proper user-defined 
> constructors/destructors and will have none in any observable future.

Yep, that was what I was referring to. I've seen many of those (and 
I think I even participated in one).  My impression was that it
wasn't something on the immediate radar.  I started looking harder
into it recently because I was given someone's library to integrate
into something else I had.  It's not the end of the world, but it
is something I wish I knew more about so that I could put forth
a better argument for.

My view is definitely narrow, so I am sure I don't see enough of the
whole picture.  It might just be too difficult in practice.

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

* Re: Extending a third party tagged type while adding finalization
  2017-11-26 17:33   ` Jere
  2017-11-26 18:15     ` Dmitry A. Kazakov
@ 2017-11-27  9:46     ` AdaMagica
  2017-11-27 12:56       ` Jere
  2017-11-27 18:10     ` Shark8
  2 siblings, 1 reply; 45+ messages in thread
From: AdaMagica @ 2017-11-27  9:46 UTC (permalink / raw)


Am Sonntag, 26. November 2017 18:33:50 UTC+1 schrieb Jere:
> Starting Test_Limited_Controlled_Mixin
> LC1: Initialize
> Extension: Initialize
> LC2: Initialize

Hm, I'm astonished about the sequence here. Components should be initialized first, then the containing object, RM 7.6(12).

LC2: Initialize
Extension: Initialize

Thus the extension has completely defined components when initialize is called.
In your example, the component LC2 is still uninitialized when extension is initialized. This looks like a bug to me.

Finalization is of course in the reverse order.


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

* Re: Extending a third party tagged type while adding finalization
  2017-11-27  9:46     ` AdaMagica
@ 2017-11-27 12:56       ` Jere
  2017-11-27 15:00         ` AdaMagica
  0 siblings, 1 reply; 45+ messages in thread
From: Jere @ 2017-11-27 12:56 UTC (permalink / raw)


On Monday, November 27, 2017 at 4:46:09 AM UTC-5, AdaMagica wrote:
> Am Sonntag, 26. November 2017 18:33:50 UTC+1 schrieb Jere:
> > Starting Test_Limited_Controlled_Mixin
> > LC1: Initialize
> > Extension: Initialize
> > LC2: Initialize
> 
> Hm, I'm astonished about the sequence here. Components should be initialized first, then the containing object, RM 7.6(12).
> 
> LC2: Initialize
> Extension: Initialize
> 
> Thus the extension has completely defined components when initialize is called.
> In your example, the component LC2 is still uninitialized when extension is initialized. This looks like a bug to me.
> 
> Finalization is of course in the reverse order.

If I understand you correctly, then I think everything may be
working as intended.  I didn't provide the code for for 
Limited_Controlled_Mixin.  It is similar to the code you 
linked to me but instead has a classwide access for 
Base.Instance as opposed to a normal access to Base.Instance.
It also does both Initialize and Finalize. In essence:

type Limited_Controlled is new Limited_Base with private;
procedure Initialize(Self : in out Limited_Controlled) is null;
procedure Finalize(Self : in out Limited_Controlled) is null;

private

type Proxy(Reference : not null access Limited_Controlled'Class) is
   new Ada.Finalization.Limited_Controlled
with null record;
procedure Finalize(Self : in out Proxy);
procedure Initialize(Self : in out Proxy);

type Limited_Controlled is new Limited_Base with record
   Impl : Proxy(Limited_Controlled'Access);
end record;


procedure Finalize(Self : in out Proxy) is
begin
   Reference.Finalize;
end Finalize;

procedure Initialize(Self : in out Proxy) is
begin
   Reference.Initialize;
end Initialize;


So based on the RM section you quoted, the I think the sequence for 
an inheritance tree of:

Base.Instance
      ||
Limited_Controlled_Mixin.Limited_Controlled
      ||
Extension.Instance

is:

1.  Components of Base.Instance
2.  Base.Instance object
3.  Components of Limited_Controlled_Mixin.Limited_Controlled 
       => Classwide access to itself
4.  Limited_Controlled_Mixin.Limited_Controlled object
5.  Components of Extension.Instance
6.  Extension.Instance object

That's assuming an ancestor tagged type is consider a component
of the descendant.  My classwide access in #3 is dispatching
to the Extension object itself, circumventing the order.  I
didn't think my design through well enough when I did that.
The intent was to be able to provide "overridable" Initialize
and Finalize to descendants of the mixin which would be called
automatically, but now I don't think that is possible in a safe way.  


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

* Re: Extending a third party tagged type while adding finalization
  2017-11-27 12:56       ` Jere
@ 2017-11-27 15:00         ` AdaMagica
  2017-11-27 16:38           ` Jere
  0 siblings, 1 reply; 45+ messages in thread
From: AdaMagica @ 2017-11-27 15:00 UTC (permalink / raw)


Am Montag, 27. November 2017 13:56:36 UTC+1 schrieb Jere:
> If I understand you correctly, then I think everything may be
> working as intended.

Yes. I didn't fully remember the contents of that paper. Everything is working as expected.

> The intent was to be able to provide "overridable" Initialize
> and Finalize to descendants of the mixin which would be called
> automatically, but now I don't think that is possible in a safe way.

Why do you say this? In my paper, Final is a further derivation, and also derivations from Final will work as expected.

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

* Re: Extending a third party tagged type while adding finalization
  2017-11-27 15:00         ` AdaMagica
@ 2017-11-27 16:38           ` Jere
  2017-11-27 18:37             ` AdaMagica
  0 siblings, 1 reply; 45+ messages in thread
From: Jere @ 2017-11-27 16:38 UTC (permalink / raw)


On Monday, November 27, 2017 at 10:00:11 AM UTC-5, AdaMagica wrote:
> Am Montag, 27. November 2017 13:56:36 UTC+1 schrieb Jere:
> > The intent was to be able to provide "overridable" Initialize
> > and Finalize to descendants of the mixin which would be called
> > automatically, but now I don't think that is possible in a safe way.
> 
> Why do you say this? In my paper, Final is a further derivation, and also derivations from Final will work as expected.

well, when I tried your example it didn't call the finalization routing for
any derived types.  I might have mis-copied it somehow.  Here is a 
compilable example:

**************************************************************
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Finalization;
with Ada.Task_Attributes;

procedure Main is
   generic

      type Uncontrolled (<>) is abstract tagged private;

      with procedure Adjust     (Object: in out Uncontrolled);
      with procedure Finalize   (Object: in out Uncontrolled);

   package To_Controlled is

      type Controlled is new Uncontrolled with private;

   private

      type Controlled_Ptr is access all Controlled;

      type Component is new Ada.Finalization.Controlled with record
         Parent: Controlled_Ptr;
      end record;

      type Controlled is new Uncontrolled with record
         Controller: Component := (Ada.Finalization.Controlled with
                                   Controlled'Unrestricted_Access);  -- Gnat only
      end record;

      procedure Adjust     (Object: in out Component);
      procedure Finalize   (Object: in out Component);

   end To_Controlled;
   
   package body To_Controlled is

      package Store is
         new Ada.Task_Attributes (Attribute     => Controlled_Ptr,
                                  Initial_Value => null);

      procedure Adjust (Object: in out Component) is
      begin
         Object.Parent := Store.Value;
         Adjust (Uncontrolled (Object.Parent.all));
      end Adjust;

      procedure Finalize (Object: in out Component) is
      begin
         Store.Set_Value (Object.Parent);
         Finalize (Uncontrolled (Object.Parent.all));
      end Finalize;

   end To_Controlled;
   
   package Components is
      type C1 is new Ada.Finalization.Controlled with null record;
      overriding procedure Adjust    (Self : in out C1);
      overriding procedure Finalize  (Self : in out C1);
      
      type C2 is new Ada.Finalization.Controlled with null record;
      overriding procedure Adjust    (Self : in out C2);
      overriding procedure Finalize  (Self : in out C2);
   end Components;
   
   package body Components is
      overriding procedure Adjust    (Self : in out C1) is
      begin
         Put_Line("Adjust C1");
      end Adjust;
      overriding procedure Finalize  (Self : in out C1) is
      begin
         Put_Line("Finalize C1");
      end Finalize;
      
      overriding procedure Adjust    (Self : in out C2) is
      begin
         Put_Line("Adjust C2");
      end Adjust;
      overriding procedure Finalize  (Self : in out C2) is
      begin
         Put_Line("Finalize C2");
      end Finalize;
   end Components;
   
   package Types is
      type Base is tagged record
         c1 : Components.C1;
      end record;
      
      type Derived is new Base with null record;
      procedure Adjust    (Self : in out Derived);
      procedure Finalize  (Self : in out Derived);
      
      package To_C is new To_Controlled
         (Derived, Adjust, Finalize);
      
      type Final is new To_C.Controlled with record
         c2 : Components.C2;
      end record;
      overriding procedure Adjust    (Self : in out Final);
      overriding procedure Finalize  (Self : in out Final);
      
   end Types;
      
   package body Types is
      procedure Adjust    (Self : in out Derived) is
      begin
         Put_Line("Adjust Derived");
      end Adjust;
      procedure Finalize  (Self : in out Derived) is
      begin
         Put_Line("Finalize Derived");
      end Finalize;
      
      procedure Adjust    (Self : in out Final) is
      begin
         Put_Line("Adjust Final");
      end Adjust;
      procedure Finalize  (Self : in out Final) is
      begin
         Put_Line("Finalize Final");
      end Finalize;
   end Types;
   
   v : Types.Final;
begin
   Put_Line ("Starting");

end Main;

**************************************************************

with this the output is:
Starting
Finalize C2
Finalize Derived
Finalize C1

There is no "Finalize Final" as expected from inheritance

Did I put something in wrong?


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

* Re: Extending a third party tagged type while adding finalization
  2017-11-26 17:33   ` Jere
  2017-11-26 18:15     ` Dmitry A. Kazakov
  2017-11-27  9:46     ` AdaMagica
@ 2017-11-27 18:10     ` Shark8
  2017-11-27 19:56       ` Jere
  2017-11-28  1:55       ` Randy Brukardt
  2 siblings, 2 replies; 45+ messages in thread
From: Shark8 @ 2017-11-27 18:10 UTC (permalink / raw)


On Sunday, November 26, 2017 at 10:33:50 AM UTC-7, Jere wrote:
> 
> What I tried to do was use a mixin but have it keep a reference to a
> classwide access on the object.  Then I tried dispatching out to the
> correct object type from there.  This kind of highlighted the evils
> of using redispatch in Ada though as I found that if I had component
> definitions like this:

JP Rosen's paper "A Naming Convention for Classes in Ada 9X" details a way you might be able to ease the pain of such constructs. 

The example of adding a "with benefits" extension to "computer scientist" which is itself an "employee" is detailed as follows:
with Employee; use Employee;
generic
     type Origin is new Employee.lnstance with private;
packaqe With_Benefits_Facet is
    type Instance is new Origin with private;
    subtype Class is Instance'Class;
    
    -- Operations to handle benefits private 
end With__Benefits_Facet;

--------------------------------

with Computer__Scientist, With_Benefits_Facet; use Computer_Scientist;
package Computer_Scientists__With__Benefits is
     new With__Benefits__Facet(Computer_Scientist. Instance); 


So, to do this sort of thing how you want, couldn't you handle things via generic?

Generic
  -- You might want to put a Base here and derive from it...
  Type Controlled is limited private;
  with procedure Initialize (Object : in out Controlled) is null;
  with procedure Adjust     (Object : in out Controlled) is null;
  with procedure Finalize   (Object : in out Controlled) is null;
Package Controlled_Mixin is
  
  Type Instance is new Ada.Finalization.Limited_Controlled with record
    Component : Controlled;
  end record;
  
  --...
End Controlled_Mixin;

> 
> Based on what I have read so far, I didn't see any discussion that would
> lead me to think this will be changed at least in the near future.  I
> wish there was a way it would be easy for vendors to do something like:
> 
> type Some_Type is tagged private;
> for Some_Type'Initialize use Initialize_Some_Type;
> for Some_Type'Adjust use Adjust_Some_Type;
> for Some_Type'Finalize use Finalize_Some_Type;
> 
> and then just have the compiler handle adding the needed structures
> to the type under the hood (like how GNAT uses Controlled to hold
> a linked list under the hood...but compiler managed).

That would be pretty nice.


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

* Re: Extending a third party tagged type while adding finalization
  2017-11-27 16:38           ` Jere
@ 2017-11-27 18:37             ` AdaMagica
  2017-11-27 19:53               ` Jere
  2017-12-03 21:53               ` Robert Eachus
  0 siblings, 2 replies; 45+ messages in thread
From: AdaMagica @ 2017-11-27 18:37 UTC (permalink / raw)


Am Montag, 27. November 2017 17:38:02 UTC+1 schrieb Jere:
> On Monday, November 27, 2017 at 10:00:11 AM UTC-5, AdaMagica wrote:
> well, when I tried your example it didn't call the finalization routing for
> any derived types.  I might have mis-copied it somehow.  Here is a 
> compilable example:
> procedure Main is
>    generic
> 
>       type Uncontrolled (<>) is abstract tagged private;
> 
>       with procedure Adjust     (Object: in out Uncontrolled);
>       with procedure Finalize   (Object: in out Uncontrolled);

The problem is in your generic parameter part. See section 3 of my paper and download the full code (see the end of the paper).

It's really a problem that opens the gates of hell as I've written as an intro.
It can definitly only work for limited types.


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

* Re: Extending a third party tagged type while adding finalization
  2017-11-27 18:37             ` AdaMagica
@ 2017-11-27 19:53               ` Jere
  2017-11-28 11:48                 ` AdaMagica
  2017-12-03 21:53               ` Robert Eachus
  1 sibling, 1 reply; 45+ messages in thread
From: Jere @ 2017-11-27 19:53 UTC (permalink / raw)


On Monday, November 27, 2017 at 1:37:22 PM UTC-5, AdaMagica wrote:
> Am Montag, 27. November 2017 17:38:02 UTC+1 schrieb Jere:
> > On Monday, November 27, 2017 at 10:00:11 AM UTC-5, AdaMagica wrote:
> > well, when I tried your example it didn't call the finalization routing for
> > any derived types.  I might have mis-copied it somehow.  Here is a 
> > compilable example:
> > procedure Main is
> >    generic
> > 
> >       type Uncontrolled (<>) is abstract tagged private;
> > 
> >       with procedure Adjust     (Object: in out Uncontrolled);
> >       with procedure Finalize   (Object: in out Uncontrolled);
> 
> The problem is in your generic parameter part. See section 3 of my paper and download the full code (see the end of the paper).
> 
> It's really a problem that opens the gates of hell as I've written as an intro.
> It can definitly only work for limited types.

Sorry about that.  I copied it from your paper (and changed some names) 
but I think I copied from the wrong place.  I downloaded code, added 
controlled components to both Parent and Final.  I saw the same results
(out of order initialization and finalization).  I don't know how you
feel about reposting your copyrighted code so here is a handmade main
linking to your code to show what I mean:

******************************************
with Ada.Text_IO; use Ada.Text_IO;
with Add_Finalization.To_Limited_Uncontrolled;
with Ada.Finalization;

procedure Main is
   
   -- Just some controlled components to add later
   package Components is
      type C1 is new Ada.Finalization.Limited_Controlled with null record;
      overriding procedure Initialize(Self : in out C1);
      overriding procedure Finalize  (Self : in out C1);

      type C2 is new Ada.Finalization.Limited_Controlled with null record;
      overriding procedure Initialize(Self : in out C2);
      overriding procedure Finalize  (Self : in out C2);
   end Components;

   package body Components is
      overriding procedure Initialize(Self : in out C1) is
      begin
         Put_Line("Initialize C1");
      end Initialize;
      overriding procedure Finalize  (Self : in out C1) is
      begin
         Put_Line("Finalize C1");
      end Finalize;

      overriding procedure Initialize(Self : in out C2) is
      begin
         Put_Line("Initialize C2");
      end Initialize;
      overriding procedure Finalize  (Self : in out C2) is
      begin
         Put_Line("Finalize C2");
      end Finalize;
   end Components;

   package Types is
      type Base is tagged limited record
         c1 : Components.C1;
      end record;

      type Derived is new Base with null record;
      procedure Initialize(Self : in out Derived);
      procedure Finalize  (Self : in out Derived);
      
      procedure Initialize_Redipatch(Self : in out Derived'Class);
      procedure Finalize_Redipatch(Self : in out Derived'Class);

      package To_LC is new Add_Finalization.To_Limited_Uncontrolled
         (Derived, Initialize_Redipatch, Finalize_Redipatch);

      type Final is new To_LC.Controlled with record
         c2 : Components.C2;
      end record;
      overriding procedure Initialize(Self : in out Final);
      overriding procedure Finalize  (Self : in out Final);

   end Types;

   package body Types is
      
      procedure Initialize_Redipatch(Self : in out Derived'Class) is
      begin
         Self.Initialize;
      end Initialize_Redipatch;
      procedure Finalize_Redipatch(Self : in out Derived'Class) is
      begin
         Self.Finalize;
      end Finalize_Redipatch;
      
      procedure Initialize(Self : in out Derived) is
      begin
         Put_Line("Initialize Derived");
      end Initialize;
      procedure Finalize  (Self : in out Derived) is
      begin
         Put_Line("Finalize Derived");
      end Finalize;

      procedure Initialize(Self : in out Final) is
      begin
         Put_Line("Initialize Final");
      end Initialize;
      procedure Finalize  (Self : in out Final) is
      begin
         Put_Line("Finalize Final");
      end Finalize;
   end Types;

   v : Types.Final;
begin
   Put_Line ("Starting");

end Main;

******************************************

The output for this is:
Initialize C1
Initialize Final
Initialize C2
Starting
Finalize C2
Finalize Final
Finalize C1

which is the same thing I was seeing with my version.  Final is initialized
before C2 and C2 is finalized before Final.  

I can repost the modified version of your code if this isn't sufficient to
show the issue.  I just wasn't sure if I should.  The output from the
modified copy of your code:

Initialize C1
Final: I am being initialized 4
Derived: I am being initialized 2147483647
Initialize C2
Global
Final: I am 100
Derived: I am 2147483647
Parent: I am-2147483648
Initialize C1
Final: I am being initialized 4
Derived: I am being initialized 2147483647
Initialize C2
Local
Final: I am 52
Derived: I am 51
Parent: I am 50
Local out of scope
Finalize C2
Final: I am being finalized.
Final: I am 52
Derived: I am 51
Parent: I am 50
Derived: I am being finalized 51
Derived: I have been finalized 0
Final: I am 0
Derived: I am 0
Parent: I am 0
Final: I have been finalized.
Finalize C1
Global
Final: I am 100
Derived: I am 2147483647
Parent: I am-2147483648
Global out of scope
Finalize C2
Final: I am being finalized.
Final: I am 100
Derived: I am 2147483647
Parent: I am-2147483648
Derived: I am being finalized 2147483647
Derived: I have been finalized 0
Final: I am 0
Derived: I am 0
Parent: I am 0
Final: I have been finalized.
Finalize C1


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

* Re: Extending a third party tagged type while adding finalization
  2017-11-27 18:10     ` Shark8
@ 2017-11-27 19:56       ` Jere
  2017-11-28  1:55       ` Randy Brukardt
  1 sibling, 0 replies; 45+ messages in thread
From: Jere @ 2017-11-27 19:56 UTC (permalink / raw)


On Monday, November 27, 2017 at 1:10:57 PM UTC-5, Shark8 wrote:
> On Sunday, November 26, 2017 at 10:33:50 AM UTC-7, Jere wrote:
> > 
> > What I tried to do was use a mixin but have it keep a reference to a
> > classwide access on the object.  Then I tried dispatching out to the
> > correct object type from there.  This kind of highlighted the evils
> > of using redispatch in Ada though as I found that if I had component
> > definitions like this:
> 
> JP Rosen's paper "A Naming Convention for Classes in Ada 9X" details a way you might be able to ease the pain of such constructs. 
> 
> The example of adding a "with benefits" extension to "computer scientist" which is itself an "employee" is detailed as follows:
> with Employee; use Employee;
> generic
>      type Origin is new Employee.lnstance with private;
> packaqe With_Benefits_Facet is
>     type Instance is new Origin with private;
>     subtype Class is Instance'Class;
>     
>     -- Operations to handle benefits private 
> end With__Benefits_Facet;
> 
> --------------------------------
> 
> with Computer__Scientist, With_Benefits_Facet; use Computer_Scientist;
> package Computer_Scientists__With__Benefits is
>      new With__Benefits__Facet(Computer_Scientist. Instance); 
> 
> 
> So, to do this sort of thing how you want, couldn't you handle things via generic?
> 
> Generic
>   -- You might want to put a Base here and derive from it...
>   Type Controlled is limited private;
>   with procedure Initialize (Object : in out Controlled) is null;
>   with procedure Adjust     (Object : in out Controlled) is null;
>   with procedure Finalize   (Object : in out Controlled) is null;
> Package Controlled_Mixin is
>   
>   Type Instance is new Ada.Finalization.Limited_Controlled with record
>     Component : Controlled;
>   end record;
>   
>   --...
> End Controlled_Mixin;
> 

Well the initial intent is that I am integrating someone else's third party
library which uses a lot of classwide parameters.  Normally I would just
extend the base type and do something similar to what you and AdaMagica
have proposed.  what I am trying to avoid is having to do this for
every descendant down the line.  I wanted to remove as much of the
burden that I can from any client code.  While having to do a separate
mixin for every descendant isn't the end of the world, I was hoping
there was a way to do a single mixin and have it propogate via 
inheritance to all later descendants.  That way a user doesn't have
to do the mixin for every new type.  I was just trying to reduce a
lot of package noise.

With the mixin approach I would need to do something like:

type New_Type1 is new Base_Type with private;
procedure Initialize(Self : in out New_Type1);
procedure Finalize  (Self : in out New_Type1);

package New_Type1_To_LC is
   new To_Limited_Controlled(New_Type1,Initialize,Finalize);

subtype New_Type1_LC is New_Type1_LC.Controlled;

type New_Type2 is new New_Type1_LC with private;
procedure Initialize(Self : in out New_Type2);
procedure Finalize  (Self : in out New_Type2);

package New_Type2_To_LC is
   new To_Limited_Controlled(New_Type2,Initialize,Finalize);

subtype New_Type2_LC is New_Type2_LC.Controlled;

VS with some (undiscovered) inheritance method:

package Limited_Controlled is new My_Limited_Controlled(Base_Type);
subtype Controlled is Limited_Controlled.Controlled;

type New_Type1 is new Controlled with private;
overriding procedure Finalize  (Self : in out New_Type1);

type New_Type2 is new New_Type1_LC with private;
overriding procedure Finalize  (Self : in out New_Type2);

In the former method, I have to define dummy procedures and
do a mixin for every new type.  In the latter method, I only
have to do it once and just inherit and override as necessary.

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

* Re: Extending a third party tagged type while adding finalization
  2017-11-27 18:10     ` Shark8
  2017-11-27 19:56       ` Jere
@ 2017-11-28  1:55       ` Randy Brukardt
  2017-12-03  2:47         ` Jere
  1 sibling, 1 reply; 45+ messages in thread
From: Randy Brukardt @ 2017-11-28  1:55 UTC (permalink / raw)


"Shark8" <onewingedshark@gmail.com> wrote in message 
news:24767ee5-cda8-45e4-98d1-7da44757bd40@googlegroups.com...
...
>> Based on what I have read so far, I didn't see any discussion that would
>> lead me to think this will be changed at least in the near future.  I
>> wish there was a way it would be easy for vendors to do something like:
>>
>> type Some_Type is tagged private;
>> for Some_Type'Initialize use Initialize_Some_Type;
>> for Some_Type'Adjust use Adjust_Some_Type;
>> for Some_Type'Finalize use Finalize_Some_Type;
>>
>> and then just have the compiler handle adding the needed structures
>> to the type under the hood (like how GNAT uses Controlled to hold
>> a linked list under the hood...but compiler managed).

This sort of thing might work in GNAT, but it would be completely impossible 
in Janus/Ada. We used an implementation strategy that follows directly from 
the Ada definition: there are hidden components that belong to type 
Ada.Finalization.Controlled, and the tag of that type has additional slots 
to support Initialize/Adjust/Finalize. Objects of controlled types get added 
to a linked list (that's what the hidden components are for), and 
Finalization happens by dispatching to the Finalize routine for each object 
on that list at the appropriate point.

A mechanism like the above would require adding those hidden components 
(which have to be at a fixed location, lest it be impossible to walk the 
linked list) to existing types, which would require moving components. That 
has no chance of working.

Keep in mind that the full type above might be declared something like:

 type Some_Type is new Some_Other_Type with null record;

where Some_Other_Type already has components that are declared in the same 
place as the controlled components.

The only way this could be made to work in Janus/Ada would be for all tagged 
types to be controlled, which would waste time and space for types that 
aren't actually controlled. Since Janus/Ada was designed to be 
space-efficient, that would be going directly against our primary goal - not 
something I'd do without a fight.

                                            Randy.




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

* Re: Extending a third party tagged type while adding finalization
  2017-11-27 19:53               ` Jere
@ 2017-11-28 11:48                 ` AdaMagica
  2017-12-03  2:22                   ` Jere
  0 siblings, 1 reply; 45+ messages in thread
From: AdaMagica @ 2017-11-28 11:48 UTC (permalink / raw)


Am Montag, 27. November 2017 20:53:59 UTC+1 schrieb Jere:
> On Monday, November 27, 2017 at 1:37:22 PM UTC-5, AdaMagica wrote:
> > The problem is in your generic parameter part. See section 3 of my paper and download the full code (see the end of the paper).
> > 
> > It's really a problem that opens the gates of hell as I've written as an intro.
> > It can definitly only work for limited types.
> 
> Sorry about that.  I copied it from your paper (and changed some names) 
> but I think I copied from the wrong place.  I downloaded code, added 
> controlled components to both Parent and Final.  I saw the same results
> (out of order initialization and finalization).  I don't know how you
> feel about reposting your copyrighted code so here is a handmade main
> linking to your code to show what I mean:

As far as I can see from browsing your code, it's the same as my code in the test program included in the zip file.
> ******************************************
> 
> The output for this is:
> Initialize C1
> Initialize Final
> Initialize C2
> Starting
> Finalize C2
> Finalize Final
> Finalize C1
> 
> which is the same thing I was seeing with my version.  Final is initialized
> before C2 and C2 is finalized before Final. 

Yes, that's a side effect of the selfreference. Too bad. 

> I can repost the modified version of your code if this isn't sufficient to
> show the issue.  I just wasn't sure if I should.  The output from the
> modified copy of your code:

There's a commented output of the test program included in my zip file.

So I think you got it working, no more problems with further derivations.

I do not think there is a copyright problem, since the code has been published in Ada Letters. If you want to use it, you may want to add a link to this magazine, so that readers of your code can find further enlightenment :-) Or keep a copy of the zip file alongside with your code.

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

* Re: Extending a third party tagged type while adding finalization
  2017-11-28 11:48                 ` AdaMagica
@ 2017-12-03  2:22                   ` Jere
  0 siblings, 0 replies; 45+ messages in thread
From: Jere @ 2017-12-03  2:22 UTC (permalink / raw)


On Tuesday, November 28, 2017 at 6:48:10 AM UTC-5, AdaMagica wrote:
> Am Montag, 27. November 2017 20:53:59 UTC+1 schrieb Jere:
> > 
> > The output for this is:
> > Initialize C1
> > Initialize Final
> > Initialize C2
> > Starting
> > Finalize C2
> > Finalize Final
> > Finalize C1
> > 
> > which is the same thing I was seeing with my version.  Final is initialized
> > before C2 and C2 is finalized before Final. 
> 
> Yes, that's a side effect of the selfreference. Too bad. 
> 

Yes indeed.  This is why I initially said it couldn't be done safely. The
self reference + dispatch causes out of order initialization and
finalization.  It can be done safely in specific cases, but not
in general.  I got this result from both my initial code and using the
code from your paper.  It makes sense now that I have had time to
think about it more.  Basically, I can add Initialization and
Finalization to a descendant, but I cannot do so in a manner that
further descendants can safely inherit it.  I have to add it to each
descendant manually (and avoid the classwide self reference) to keep safety.

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

* Re: Extending a third party tagged type while adding finalization
  2017-11-28  1:55       ` Randy Brukardt
@ 2017-12-03  2:47         ` Jere
  2017-12-03  9:29           ` Dmitry A. Kazakov
  2017-12-04 20:54           ` Randy Brukardt
  0 siblings, 2 replies; 45+ messages in thread
From: Jere @ 2017-12-03  2:47 UTC (permalink / raw)


On Monday, November 27, 2017 at 8:55:19 PM UTC-5, Randy Brukardt wrote:
> "Jere" wrote in message 
> ...
> >> Based on what I have read so far, I didn't see any discussion that would
> >> lead me to think this will be changed at least in the near future.  I
> >> wish there was a way it would be easy for vendors to do something like:
> >>
> >> type Some_Type is tagged private;
> >> for Some_Type'Initialize use Initialize_Some_Type;
> >> for Some_Type'Adjust use Adjust_Some_Type;
> >> for Some_Type'Finalize use Finalize_Some_Type;
> >>
> >> and then just have the compiler handle adding the needed structures
> >> to the type under the hood (like how GNAT uses Controlled to hold
> >> a linked list under the hood...but compiler managed).
> 
> The only way this could be made to work in Janus/Ada would be for all tagged 
> types to be controlled, which would waste time and space for types that 
> aren't actually controlled. Since Janus/Ada was designed to be 
> space-efficient, that would be going directly against our primary goal - not 
> something I'd do without a fight.
> 
>                                             Randy.

Well, I am definitely not advocating that all tagged types need to be
controlled.  I was just musing about whether there was a different way
to do it.  The Ada Finalization method is very clunky and can be
limiting at times.  There may not be a better way to do it.  At the
end of the day, I find a lot of the errors our programmers make is
forgetting to put in a Create/Intialize or Clean_Up/Finalize call 
on objects that do not have Controlled ancestors.  It's a 
maintenance headache, so I look for ways to try to remedy that via 
design. 

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

* Re: Extending a third party tagged type while adding finalization
  2017-12-03  2:47         ` Jere
@ 2017-12-03  9:29           ` Dmitry A. Kazakov
  2017-12-03 15:10             ` AdaMagica
  2017-12-03 19:34             ` AdaMagica
  2017-12-04 20:54           ` Randy Brukardt
  1 sibling, 2 replies; 45+ messages in thread
From: Dmitry A. Kazakov @ 2017-12-03  9:29 UTC (permalink / raw)


On 2017-12-03 03:47, Jere wrote:

> Well, I am definitely not advocating that all tagged types need to be
> controlled.

Certainly all types must be, including scalars, arrays, tasks and 
class-wide types.

Having class-wide initialization and finalization is essential if there 
are task components or class-wide access components (Rosen's trick):

    type T is new Ada.Finalization.Controlled with record
       Self : not null access T'Class;
    end record;
    procedure Initialize (X : in out T);
    procedure Foo (X : in out T) is abstract;

    type S is new T with ...
    overriding procedure Foo (X : in out S);

    procedure Initialize (X : in out T) is
    begin
       X.Self.Foo; -- Boom!
    end Initialize;

Dispatching calls must be illegal during type-specific 
initialization/finalization. They are OK after these in the class-wide 
initialization or before in the class-wide finalization.

> I was just musing about whether there was a different way
> to do it.

Yes, there is no need to keep lists of objects. It is enough to have 
only static analysis to decide what kind of finalization to call. Nobody 
cares about finalization of implicitly collected objects, it is a bug 
anyway.

> The Ada Finalization method is very clunky and can be
> limiting at times.  There may not be a better way to do it.  At the
> end of the day, I find a lot of the errors our programmers make is
> forgetting to put in a Create/Intialize or Clean_Up/Finalize call
> on objects that do not have Controlled ancestors.  It's a
> maintenance headache, so I look for ways to try to remedy that via
> design.

Welcome in the club.

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


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

* Re: Extending a third party tagged type while adding finalization
  2017-12-03  9:29           ` Dmitry A. Kazakov
@ 2017-12-03 15:10             ` AdaMagica
  2017-12-03 16:39               ` Dmitry A. Kazakov
  2017-12-03 19:34             ` AdaMagica
  1 sibling, 1 reply; 45+ messages in thread
From: AdaMagica @ 2017-12-03 15:10 UTC (permalink / raw)


Am Sonntag, 3. Dezember 2017 10:29:07 UTC+1 schrieb Dmitry A. Kazakov:
>     type T is new Ada.Finalization.Controlled with record
>        Self : not null access T'Class;
>     end record;
>     procedure Initialize (X : in out T);
>     procedure Foo (X : in out T) is abstract;
> 
>     type S is new T with ...
>     overriding procedure Foo (X : in out S);
> 
>     procedure Initialize (X : in out T) is
>     begin
>        X.Self.Foo; -- Boom!
>     end Initialize;

Again an example of cryptic code I do not understand what it is aimed at to demonstrate. All I can see is that it is illegal Ada.


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

* Re: Extending a third party tagged type while adding finalization
  2017-12-03 15:10             ` AdaMagica
@ 2017-12-03 16:39               ` Dmitry A. Kazakov
  0 siblings, 0 replies; 45+ messages in thread
From: Dmitry A. Kazakov @ 2017-12-03 16:39 UTC (permalink / raw)


On 2017-12-03 16:10, AdaMagica wrote:
> Am Sonntag, 3. Dezember 2017 10:29:07 UTC+1 schrieb Dmitry A. Kazakov:
>>      type T is new Ada.Finalization.Controlled with record
>>         Self : not null access T'Class;
>>      end record;
>>      procedure Initialize (X : in out T);
>>      procedure Foo (X : in out T) is abstract;
>>
>>      type S is new T with ...
>>      overriding procedure Foo (X : in out S);
>>
>>      procedure Initialize (X : in out T) is
>>      begin
>>         X.Self.Foo; -- Boom!
>>      end Initialize;
> 
> Again an example of cryptic code I do not understand what it is
> aimed  at to demonstrate.

It demonstrates dispatch from Initialize (of T) to a procedure (Foo) of 
the derived type (S) before the derived type's Initialize is called.

> All I can see is that it is illegal Ada.

It is perfectly legal Ada. Initialize is not a constructor, it is just a 
primitive operation. So there is no promises made and no promises to 
fulfill regarding its semantics. One can call it anywhere, any number of 
times, in any order, everything is up to the unfortunate programmer.

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


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

* Re: Extending a third party tagged type while adding finalization
  2017-12-03  9:29           ` Dmitry A. Kazakov
  2017-12-03 15:10             ` AdaMagica
@ 2017-12-03 19:34             ` AdaMagica
  2017-12-03 19:41               ` Dmitry A. Kazakov
  1 sibling, 1 reply; 45+ messages in thread
From: AdaMagica @ 2017-12-03 19:34 UTC (permalink / raw)


Am Sonntag, 3. Dezember 2017 10:29:07 UTC+1 schrieb Dmitry A. Kazakov:
Didn't try to compile but can't be legal. Nonabstract type has abstract primitive operation. not null anonymous access type has nothing assigned.

>     type T is new Ada.Finalization.Controlled with record
>        Self : not null access T'Class;
>     end record;
>     procedure Initialize (X : in out T);
>     procedure Foo (X : in out T) is abstract;
> 
>     type S is new T with ...
>     overriding procedure Foo (X : in out S);
> 
>     procedure Initialize (X : in out T) is
>     begin
>        X.Self.Foo; -- Boom!
>     end Initialize;
> 
> Dispatching calls must be illegal during type-specific 
> initialization/finalization. They are OK after these in the class-wide 
> initialization or before in the class-wide finalization.
> 
> > I was just musing about whether there was a different way
> > to do it.
> 
> Yes, there is no need to keep lists of objects. It is enough to have 
> only static analysis to decide what kind of finalization to call. Nobody 
> cares about finalization of implicitly collected objects, it is a bug 
> anyway.
> 
> > The Ada Finalization method is very clunky and can be
> > limiting at times.  There may not be a better way to do it.  At the
> > end of the day, I find a lot of the errors our programmers make is
> > forgetting to put in a Create/Intialize or Clean_Up/Finalize call
> > on objects that do not have Controlled ancestors.  It's a
> > maintenance headache, so I look for ways to try to remedy that via
> > design.
> 
> Welcome in the club.
> 
> -- 
> Regards,
> Dmitry A. Kazakov
> http://www.dmitry-kazakov.de


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

* Re: Extending a third party tagged type while adding finalization
  2017-12-03 19:34             ` AdaMagica
@ 2017-12-03 19:41               ` Dmitry A. Kazakov
  2017-12-04 12:38                 ` AdaMagica
  0 siblings, 1 reply; 45+ messages in thread
From: Dmitry A. Kazakov @ 2017-12-03 19:41 UTC (permalink / raw)


On 2017-12-03 20:34, AdaMagica wrote:
> Am Sonntag, 3. Dezember 2017 10:29:07 UTC+1 schrieb Dmitry A. Kazakov:

> Didn't try to compile but can't be legal. Nonabstract type has
> abstract primitive operation. not null anonymous access type has nothing
> assigned.

Both typo errors/omissions are irrelevant to the point (of 
initialization ordering):

     type T is new Ada.Finalization.Controlled with record
        Self : not null access T'Class := T'Unchecked_Access;
     end record;
     procedure Initialize (X : in out T);
     procedure Foo (X : in out T) is null;
-------------------------------------------------------------
     procedure Initialize (X : in out T) is
     begin
        X.Self.Foo; -- Boom!
     end Initialize;
-------------------------------------------------------------
     type S is new T with null record;
     overriding procedure Foo (X : in out S);

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


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

* Re: Extending a third party tagged type while adding finalization
  2017-11-27 18:37             ` AdaMagica
  2017-11-27 19:53               ` Jere
@ 2017-12-03 21:53               ` Robert Eachus
  2017-12-04  7:58                 ` Dmitry A. Kazakov
  1 sibling, 1 reply; 45+ messages in thread
From: Robert Eachus @ 2017-12-03 21:53 UTC (permalink / raw)


On Monday, November 27, 2017 at 1:37:22 PM UTC-5, AdaMagica wrote:
 
> It's really a problem that opens the gates of hell as I've written as an intro.

I wish I'd said that! There are some things that the human mind is not designed to deal with day after day.  I'd work on code that used finalization (and derivation) for a day two, then come back to it next week.  It was as bad as working with the SQL cursor in Ada code.  Um, probably worse.

> It can definitely only work for limited types.

The problem here is that it can be made to work for non-limited types, but you have to use handles to mix limited and non-limited types.  See previous line.

I started thinking recently about how to do model, view, controller "right" in Ada. My current conclusion is that we need a set of tools that can take a model description (assume for now pure Ada) and (for example) a set of tests, the tools would then generate the display for the model and input scenarios/scripts that created the test conditions.  The original Ada model would get decorated (a lot) by the necessary input procedures and display functions.

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

* Re: Extending a third party tagged type while adding finalization
  2017-12-03 21:53               ` Robert Eachus
@ 2017-12-04  7:58                 ` Dmitry A. Kazakov
  2017-12-04 14:59                   ` Robert Eachus
  0 siblings, 1 reply; 45+ messages in thread
From: Dmitry A. Kazakov @ 2017-12-04  7:58 UTC (permalink / raw)


On 03/12/2017 22:53, Robert Eachus wrote:

> I started thinking recently about how to do model, view, controller
> "right" in Ada. My current conclusion is that we need a set of tools
> that can take a model description (assume for now pure Ada) and (for
> example) a set of tests, the tools would then generate the display for
> the model and input scenarios/scripts that created the test conditions.
> The original Ada model would get decorated (a lot) by the necessary
> input procedures and display functions.

You mean MVC using all static object? I don't think that is possible 
with or without tools.

Then I don't see how finalization might be relevant here. MVC requires 
handling dependencies, best in the form of strong and weak references 
between the actors. That works perfectly well in Ada, actually. I don't 
remember any problems implementing MVC or binding to MVC implementations 
(e.g. from GTK).

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


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

* Re: Extending a third party tagged type while adding finalization
  2017-12-03 19:41               ` Dmitry A. Kazakov
@ 2017-12-04 12:38                 ` AdaMagica
  2017-12-04 13:19                   ` AdaMagica
  0 siblings, 1 reply; 45+ messages in thread
From: AdaMagica @ 2017-12-04 12:38 UTC (permalink / raw)


Still illegal!

Am Sonntag, 3. Dezember 2017 20:41:30 UTC+1 schrieb Dmitry A. Kazakov:
> Both typo errors/omissions are irrelevant to the point (of 
> initialization ordering):
> 
>      type T is new Ada.Finalization.Controlled with record
>         Self : not null access T'Class := T'Unchecked_Access;
GNAT complains: current instance must be an immutably limited type
>      end record;

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

* Re: Extending a third party tagged type while adding finalization
  2017-12-04 12:38                 ` AdaMagica
@ 2017-12-04 13:19                   ` AdaMagica
  2017-12-04 13:55                     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 45+ messages in thread
From: AdaMagica @ 2017-12-04 13:19 UTC (permalink / raw)


Am Montag, 4. Dezember 2017 13:38:05 UTC+1 schrieb AdaMagica:
> Still illegal!
> 
> Am Sonntag, 3. Dezember 2017 20:41:30 UTC+1 schrieb Dmitry A. Kazakov:
> > Both typo errors/omissions are irrelevant to the point (of 
> > initialization ordering):
> > 
> >      type T is new Ada.Finalization.Controlled with record
> >         Self : not null access T'Class := T'Unchecked_Access;
> GNAT complains: current instance must be an immutably limited type
> >      end record;

The example can be made legal by making T limited.

But:

There is no Initialize defined for derived S. This is defined then implicitly as:

  procedure Initialize (X: in out S) is
  begin
    Initialize (T (X));
  end Initialize;

This is the calling sequence:
Init S
Init T
Foo  S

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

* Re: Extending a third party tagged type while adding finalization
  2017-12-04 13:19                   ` AdaMagica
@ 2017-12-04 13:55                     ` Dmitry A. Kazakov
  2017-12-04 15:44                       ` AdaMagica
  0 siblings, 1 reply; 45+ messages in thread
From: Dmitry A. Kazakov @ 2017-12-04 13:55 UTC (permalink / raw)


On 04/12/2017 14:19, AdaMagica wrote:

> There is no Initialize defined for derived S. This is defined then implicitly as:
> 
>    procedure Initialize (X: in out S) is
>    begin
>      Initialize (T (X));
>    end Initialize;
> 
> This is the calling sequence:
> Init S
> Init T
> Foo  S

Which is a wrong sequence per Ada design. Actually it is just

    Initialize of S

This wrong sequence is fixed in practice by applying the pattern:

    procedure Initialize (X : in out Derived) is
    begin
       Parent (X).Initialize; -- Ensure parent's initialization
       <do user initialization of Derived>
    end Initialize;

Using the pattern you get a semantically correct sequence:

       -- enter Initialize of S
       --   enter Initialize of T
    <do user initialization of T>
       --   leave Initialize of T
    <do user initialization of S>
       -- leave Initialize of S

But with Foo it becomes wrong again:

    <do user initialization of T> + call Foo of S
    <do user initialization of S>

Which is catastrophic and there is *no* way to make it right in presence 
of multiple derived types. You cannot announce a call to a deferred 
implementation during initialization of a specific type T. That may 
happen only after initializations of all derived specific types are 
complete.

Semantically it means that it must be called in the initialization of 
T'Class. The proper sequence must be:

    <do user initialization of T>
    <do user initialization of S>
    <do user initialization of S'Class>
    <do user initialization of T'Class> + call Foo of S

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


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

* Re: Extending a third party tagged type while adding finalization
  2017-12-04  7:58                 ` Dmitry A. Kazakov
@ 2017-12-04 14:59                   ` Robert Eachus
  2017-12-04 15:39                     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 45+ messages in thread
From: Robert Eachus @ 2017-12-04 14:59 UTC (permalink / raw)


On Monday, December 4, 2017 at 2:58:25 AM UTC-5, Dmitry A. Kazakov wrote:

> You mean MVC using all static object? I don't think that is possible 
> with or without tools.

No, I mean/meant to have it possible to write the model, view, and controller separately, then have a tool combine the three aspects.  So the controller could be used to do multiple changes, then a call to run causes an initial call to display. The controller will also make calls to display, as will the model from time to time (modeled time in a simulation, or test harness).

The goal is not only to make it easier for the programmer to think about the different aspects while programming them, but to minimize the scaffolding that the programmer must write.  Done well, the view mode would use default values for display objects and it would be possible for the programmer/user to move things around, resize them, change fonts and colors, and save all this in a config file.
> 
> Then I don't see how finalization might be relevant here. MVC requires 
> handling dependencies, best in the form of strong and weak references 
> between the actors. That works perfectly well in Ada, actually. I don't 
> remember any problems implementing MVC or binding to MVC implementations 
> (e.g. from GTK).


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

* Re: Extending a third party tagged type while adding finalization
  2017-12-04 14:59                   ` Robert Eachus
@ 2017-12-04 15:39                     ` Dmitry A. Kazakov
  0 siblings, 0 replies; 45+ messages in thread
From: Dmitry A. Kazakov @ 2017-12-04 15:39 UTC (permalink / raw)


On 04/12/2017 15:59, Robert Eachus wrote:
> On Monday, December 4, 2017 at 2:58:25 AM UTC-5, Dmitry A. Kazakov wrote:
> 
>> You mean MVC using all static object? I don't think that is possible
>> with or without tools.
> 
> No, I mean/meant to have it possible to write the model, view, and
> controller separately, then have a tool combine the three aspects.
Why a tool? What's wrong with connecting/attaching instances?

> So the controller could be used to do multiple changes, then a call
> to run causes an initial call to display.

Usual technique is to freeze view notification when doing bulk updates 
to the model. The easiest way is to detach all views, do updates and 
attach them back. This is how GTK deals with MVC.

> The controller will also make calls to display, as will the model
> from time to time (modeled time in a simulation, or test harness).

MVC is a synchronous model which pushes updates. If you aim at real-time 
systems you would rather use a view that pulls periodically regardless 
of any updates. That is not classical MVC.

> The goal is not only to make it easier for the programmer to think
> about the different aspects while programming them, but to minimize the
> scaffolding that the programmer must write. Done well, the view mode
> would use default values for display objects and it would be possible
> for the programmer/user to move things around, resize them, change fonts
> and colors, and save all this in a config file.

Most frameworks separate all that from whatever model. These things 
handled as properties/styles of the widgets of which the view is 
constructed. Throwing all into one heap won't make things easier, IMO.

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


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

* Re: Extending a third party tagged type while adding finalization
  2017-12-04 13:55                     ` Dmitry A. Kazakov
@ 2017-12-04 15:44                       ` AdaMagica
  2017-12-04 16:19                         ` Dmitry A. Kazakov
  0 siblings, 1 reply; 45+ messages in thread
From: AdaMagica @ 2017-12-04 15:44 UTC (permalink / raw)


Aha, now I see what you are talking about. That's what I meant with cryptic message. You too often just expect mind reading (especially difficult with illegal code snippets).

Am Montag, 4. Dezember 2017 14:55:23 UTC+1 schrieb Dmitry A. Kazakov:
> On 04/12/2017 14:19, AdaMagica wrote:
> 
> > There is no Initialize defined for derived S. This is defined then implicitly as:
> > 
> >    procedure Initialize (X: in out S) is
> >    begin
> >      Initialize (T (X));
> >    end Initialize;
> > 
> > This is the calling sequence:
> > Init S
> > Init T
> > Foo  S
> 
> Which is a wrong sequence per Ada design. Actually it is just
> 
>     Initialize of S
> 
> This wrong sequence is fixed in practice by applying the pattern:
> 
>     procedure Initialize (X : in out Derived) is
>     begin
>        Parent (X).Initialize; -- Ensure parent's initialization
>        <do user initialization of Derived>
>     end Initialize;
> 
> Using the pattern you get a semantically correct sequence:
> 
>        -- enter Initialize of S
>        --   enter Initialize of T
>     <do user initialization of T>
>        --   leave Initialize of T
>     <do user initialization of S>
>        -- leave Initialize of S

That's the well-known Ada pattern you find in any text book. So what's your point?

> But with Foo it becomes wrong again:
> 
>     <do user initialization of T> + call Foo of S
>     <do user initialization of S>

Yes, because you specifically request a redispatch via the classwide pointer. You can correct this with

  procedure Initialize (X: in out T) is
  begin
    T (X.Self.all).Foo; -- no more Boom!
  end Initialize;

There were some discussions in CLA about not to use dispatch in Initialize et alii.

> Which is catastrophic and there is *no* way to make it right in presence 
> of multiple derived types. You cannot announce a call to a deferred 
> implementation during initialization of a specific type T. That may 
> happen only after initializations of all derived specific types are 
> complete.
> 
> Semantically it means that it must be called in the initialization of 
> T'Class. The proper sequence must be:
> 
>     <do user initialization of T>
>     <do user initialization of S>
>     <do user initialization of S'Class>
>     <do user initialization of T'Class> + call Foo of S

What do you mean by init of S'Class? There are no components of an S'Class. Sorry, I don't understand.

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

* Re: Extending a third party tagged type while adding finalization
  2017-12-04 15:44                       ` AdaMagica
@ 2017-12-04 16:19                         ` Dmitry A. Kazakov
  0 siblings, 0 replies; 45+ messages in thread
From: Dmitry A. Kazakov @ 2017-12-04 16:19 UTC (permalink / raw)


On 04/12/2017 16:44, AdaMagica wrote:
> Aha, now I see what you are talking about. That's what I meant with cryptic message. You too often just expect mind reading (especially difficult with illegal code snippets).
> 
> Am Montag, 4. Dezember 2017 14:55:23 UTC+1 schrieb Dmitry A. Kazakov:

>> Which is catastrophic and there is *no* way to make it right in presence
>> of multiple derived types. You cannot announce a call to a deferred
>> implementation during initialization of a specific type T. That may
>> happen only after initializations of all derived specific types are
>> complete.
>>
>> Semantically it means that it must be called in the initialization of
>> T'Class. The proper sequence must be:
>>
>>      <do user initialization of T>
>>      <do user initialization of S>
>>      <do user initialization of S'Class>
>>      <do user initialization of T'Class> + call Foo of S
> 
> What do you mean by init of S'Class? There are no components of an
> S'Class. Sorry, I don't understand.
Then user initialization of S'Class is null.

The point is that in order to initialize a type that supports view 
conversion to a class-wide type (e.g. S'Class), the instance must be 
initialized as the corresponding class-wide type to be any time ready 
for that conversion.

In Ada there is no way to provide a user-defined hook on that 
initialization.

BTW, the class-wide initialization is not always null in Ada as one 
might think. When there is a task component ARM requires task activation 
to happen *after* calling all Initializes, which is logical, such tasks 
usually have class-wide discriminants. This is the point of class-wide 
initialization.

If we wanted to make a dispatching call to Foo safe we would need to 
have an Initialize for the corresponding class and put it there. And we 
could communicate with our task components there, which is presently 
impossible (and rightly so during type-specific initialization).

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

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

* Re: Extending a third party tagged type while adding finalization
  2017-12-03  2:47         ` Jere
  2017-12-03  9:29           ` Dmitry A. Kazakov
@ 2017-12-04 20:54           ` Randy Brukardt
  2017-12-04 21:02             ` Dmitry A. Kazakov
  1 sibling, 1 reply; 45+ messages in thread
From: Randy Brukardt @ 2017-12-04 20:54 UTC (permalink / raw)


"Jere" <jhb.chat@gmail.com> wrote in message 
news:037e7f02-9149-4648-b7c5-91f67c1c1961@googlegroups.com...
> On Monday, November 27, 2017 at 8:55:19 PM UTC-5, Randy Brukardt wrote:
>> "Jere" wrote in message
>> ...
>> >> Based on what I have read so far, I didn't see any discussion that 
>> >> would
>> >> lead me to think this will be changed at least in the near future.  I
>> >> wish there was a way it would be easy for vendors to do something 
>> >> like:
>> >>
>> >> type Some_Type is tagged private;
>> >> for Some_Type'Initialize use Initialize_Some_Type;
>> >> for Some_Type'Adjust use Adjust_Some_Type;
>> >> for Some_Type'Finalize use Finalize_Some_Type;
>> >>
>> >> and then just have the compiler handle adding the needed structures
>> >> to the type under the hood (like how GNAT uses Controlled to hold
>> >> a linked list under the hood...but compiler managed).
>>
>> The only way this could be made to work in Janus/Ada would be for all 
>> tagged
>> types to be controlled, which would waste time and space for types that
>> aren't actually controlled. Since Janus/Ada was designed to be
>> space-efficient, that would be going directly against our primary goal - 
>> not
>> something I'd do without a fight.
>
> Well, I am definitely not advocating that all tagged types need to be
> controlled.  I was just musing about whether there was a different way
> to do it.  The Ada Finalization method is very clunky and can be
> limiting at times.  There may not be a better way to do it.  At the
> end of the day, I find a lot of the errors our programmers make is
> forgetting to put in a Create/Intialize or Clean_Up/Finalize call
> on objects that do not have Controlled ancestors.  It's a
> maintenance headache, so I look for ways to try to remedy that via
> design.

My personal opinion is that all newly designed ADTs should be derived from 
Controlled (or Limited_Controlled, if limited), even if there is no 
immediate need for finalization. That's especially true if extensions are 
expected; one doesn't want to put unnecessary limitations on extensions.

The sort things that can't afford to be controlled are those that aren't 
really ADTs anyway (think coordinates of a windows).

                                     Randy.



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

* Re: Extending a third party tagged type while adding finalization
  2017-12-04 20:54           ` Randy Brukardt
@ 2017-12-04 21:02             ` Dmitry A. Kazakov
  2017-12-05 21:09               ` Randy Brukardt
  0 siblings, 1 reply; 45+ messages in thread
From: Dmitry A. Kazakov @ 2017-12-04 21:02 UTC (permalink / raw)


On 2017-12-04 21:54, Randy Brukardt wrote:

> The sort things that can't afford to be controlled are those that aren't
> really ADTs anyway (think coordinates of a windows).

What? Window coordinates are a perfect example of ADT. There are lots of 
quite specific operations defined on coordinates which are beyond normal 
arithmetic: scaling, rotation, moving, relative to absolute conversions, 
logical to physical conversions, coordinate systems, scalar and vector 
products, coordinate translation ... the list is almost infinite.

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

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

* Re: Extending a third party tagged type while adding finalization
  2017-12-04 21:02             ` Dmitry A. Kazakov
@ 2017-12-05 21:09               ` Randy Brukardt
  2017-12-05 21:29                 ` Dmitry A. Kazakov
  0 siblings, 1 reply; 45+ messages in thread
From: Randy Brukardt @ 2017-12-05 21:09 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:p04d5g$6jd$1@gioia.aioe.org...
> On 2017-12-04 21:54, Randy Brukardt wrote:
>
>> The sort things that can't afford to be controlled are those that aren't
>> really ADTs anyway (think coordinates of a windows).
>
> What? Window coordinates are a perfect example of ADT. There are lots of 
> quite specific operations defined on coordinates which are beyond normal 
> arithmetic: scaling, rotation, moving, relative to absolute conversions, 
> logical to physical conversions, coordinate systems, scalar and vector 
> products, coordinate translation ... the list is almost infinite.

ADT = "abstract data type". And there is nothing "abstract" about 
coordinates, where you usually want to use an aggregate of X and Y values to 
create them. Just because the type isn't private doesn't mean that you can't 
have operations on them (Janus/Ada internally has essentially no private 
types, but there sure are a lot of operations :-).

The sorts of things that one doesn't want to make controlled also tend to be 
the sorts of things that one doesn't want to make private. Ergo, my advice 
above. As always, YMMV.

                                          Randy.



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

* Re: Extending a third party tagged type while adding finalization
  2017-12-05 21:09               ` Randy Brukardt
@ 2017-12-05 21:29                 ` Dmitry A. Kazakov
  2017-12-07  1:13                   ` Randy Brukardt
  0 siblings, 1 reply; 45+ messages in thread
From: Dmitry A. Kazakov @ 2017-12-05 21:29 UTC (permalink / raw)


On 2017-12-05 22:09, Randy Brukardt wrote:
> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
> news:p04d5g$6jd$1@gioia.aioe.org...
>> On 2017-12-04 21:54, Randy Brukardt wrote:
>>
>>> The sort things that can't afford to be controlled are those that aren't
>>> really ADTs anyway (think coordinates of a windows).
>>
>> What? Window coordinates are a perfect example of ADT. There are lots of
>> quite specific operations defined on coordinates which are beyond normal
>> arithmetic: scaling, rotation, moving, relative to absolute conversions,
>> logical to physical conversions, coordinate systems, scalar and vector
>> products, coordinate translation ... the list is almost infinite.
> 
> ADT = "abstract data type". And there is nothing "abstract" about
> coordinates, where you usually want to use an aggregate of X and Y values to
> create them. Just because the type isn't private doesn't mean that you can't
> have operations on them (Janus/Ada internally has essentially no private
> types, but there sure are a lot of operations :-).

I don't know your definition of ADT, but mine is in agreement with 
Wikipedia:

"In computer science, an abstract data type (ADT) is a mathematical 
model for data types, where a data type is defined by its behavior 
(semantics) from the point of view of a user of the data, specifically 
in terms of possible values, possible operations on data of this type, 
and the behavior of these operations. This contrasts with data 
structures, which are concrete representations of data, and are the 
point of view of an implementer, not a user."

> The sorts of things that one doesn't want to make controlled also tend to be
> the sorts of things that one doesn't want to make private. Ergo, my advice
> above. As always, YMMV.

Initialization and finalization are properties of ADT only when these 
are related to its behavior/semantics. The semantics of coordinates does 
not require the implementation to provide any initialization or 
finalization beyond default. That does not make it less ADT.

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

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

* Re: Extending a third party tagged type while adding finalization
  2017-12-05 21:29                 ` Dmitry A. Kazakov
@ 2017-12-07  1:13                   ` Randy Brukardt
  2017-12-07  8:36                     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 45+ messages in thread
From: Randy Brukardt @ 2017-12-07  1:13 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:p07343$1tst$1@gioia.aioe.org...
> On 2017-12-05 22:09, Randy Brukardt wrote:
...
> I don't know your definition of ADT, but mine is in agreement with 
> Wikipedia:
>
> "In computer science, an abstract data type (ADT) is a mathematical model 
> for data types, where a data type is defined by its behavior (semantics) 
> from the point of view of a user of the data, specifically in terms of 
> possible values, possible operations on data of this type, and the 
> behavior of these operations. This contrasts with data structures, which 
> are concrete representations of data, and are the point of view of an 
> implementer, not a user."

Mathematical model? By that definition, I'll never write an ADT. The above 
is much too complex. It could be simplified a lot:

An ADT is a data type (from the perspective of a client of a type) defined 
solely by the operations defined for that data type.

For Ada, this means that an ADT is a private type (possibly tagged) with 
(usually explicit) primitive operations, and that there are no end-runs on 
those primitive operations. All other uses of the ADT are built out of those 
primitives.

If a type is not private, it cannot be an ADT, as it provides an unlimited 
number of other operations that are not described explicitly. With the 
Wikipedia definition above, every Ada data type is an ADT, since every type 
can be described this way (every operation on a numeric type is described by 
the Ada Standard, after all, and a client can use nothing else). That's a 
completely useless definition.

(Yes, I'm ignoring "=" and ":=" for this definition; arguably, only limited 
types can be ADTs as everything ought to be explicitly defined [or 
inherited]. I won't go that far, but the number of implicit operations of an 
ADT should be very small. A numeric type can never be an ADT, IMHO.).

>> The sorts of things that one doesn't want to make controlled also tend to 
>> be
>> the sorts of things that one doesn't want to make private. Ergo, my 
>> advice
>> above. As always, YMMV.
>
> Initialization and finalization are properties of ADT only when these are 
> related to its behavior/semantics. The semantics of coordinates does not 
> require the implementation to provide any initialization or finalization 
> beyond default. That does not make it less ADT.

The Wikipedia definition you give describes a data type (any data type), and 
thus is useless. I believe that an Ada type has to be private to be an ADT, 
and thus coordinates (for one example) are best not being described as an 
ADT. One COULD build a coordinate ADT, but they'd be working a lot harder 
than necessary, and there would be no possible gain from doing so (the 
coordinate system of a target system never changes).

                                      Randy.


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

* Re: Extending a third party tagged type while adding finalization
  2017-12-07  1:13                   ` Randy Brukardt
@ 2017-12-07  8:36                     ` Dmitry A. Kazakov
  2017-12-07 23:22                       ` Randy Brukardt
  0 siblings, 1 reply; 45+ messages in thread
From: Dmitry A. Kazakov @ 2017-12-07  8:36 UTC (permalink / raw)


On 07/12/2017 02:13, Randy Brukardt wrote:
> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
> news:p07343$1tst$1@gioia.aioe.org...
>> On 2017-12-05 22:09, Randy Brukardt wrote:
> ...
>> I don't know your definition of ADT, but mine is in agreement with
>> Wikipedia:
>>
>> "In computer science, an abstract data type (ADT) is a mathematical model
>> for data types, where a data type is defined by its behavior (semantics)
>> from the point of view of a user of the data, specifically in terms of
>> possible values, possible operations on data of this type, and the
>> behavior of these operations. This contrasts with data structures, which
>> are concrete representations of data, and are the point of view of an
>> implementer, not a user."
> 
> Mathematical model? By that definition, I'll never write an ADT.

Of course you do. There is no way any computer implementation to have no 
mathematical model. Unless you are working with a jigsaw on your 
computer box ...

Programming is not science, not even much an applied science. It has no 
truths of its own.

> The above
> is much too complex. It could be simplified a lot:
> 
> An ADT is a data type (from the perspective of a client of a type) defined
> solely by the operations defined for that data type.

1. That does not apply to Ada since it has named type matching. 
Therefore you can have two different types with identical operations.

2. You cannot do anything with a type otherwise than through its 
operations. So the definition would be useless without splitting 
operations into "operations operations" and not "quite operations", 
which you apparently trying to do.

> For Ada, this means that an ADT is a private type (possibly tagged) with
> (usually explicit) primitive operations, and that there are no end-runs on
> those primitive operations. All other uses of the ADT are built out of those
> primitives.

Why does it follow?

1. Private type means that parts of the representation is hidden. Your 
definition is not related to that.

2. Primitiveness of an operation is not related either.

> If a type is not private, it cannot be an ADT, as it provides an unlimited
> number of other operations that are not described explicitly.

How primitiveness changes that? I still can define new subprograms 
taking and returning values of the type regardless. Adding new 
operations does not alter the semantics of ADT. Overriding could.

> With the
> Wikipedia definition above, every Ada data type is an ADT, since every type
> can be described this way (every operation on a numeric type is described by
> the Ada Standard, after all, and a client can use nothing else). That's a
> completely useless definition.

ADT is the semantics it implements. You first have the semantics 
(mathematical model of the problem space) and then an implementation of.

Non-ADT is ad-hoc semantics deduced from a given representation. You 
take 'int' from the compiler and then try to figure out if it can be 
useful for you.

That is the difference.

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

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

* Re: Extending a third party tagged type while adding finalization
  2017-12-07  8:36                     ` Dmitry A. Kazakov
@ 2017-12-07 23:22                       ` Randy Brukardt
  2017-12-08  9:30                         ` Dmitry A. Kazakov
  0 siblings, 1 reply; 45+ messages in thread
From: Randy Brukardt @ 2017-12-07 23:22 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:p0auie$h5h$1@gioia.aioe.org...
> On 07/12/2017 02:13, Randy Brukardt wrote:
>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>> news:p07343$1tst$1@gioia.aioe.org...
>>> On 2017-12-05 22:09, Randy Brukardt wrote:
>> ...
>> The above
>> is much too complex. It could be simplified a lot:
>>
>> An ADT is a data type (from the perspective of a client of a type) 
>> defined
>> solely by the operations defined for that data type.

This was a bit sloppy; it should also have required the operations to be 
defined explicitly and as a closed set of operations.

> 1. That does not apply to Ada since it has named type matching. Therefore 
> you can have two different types with identical operations.

This doesn't seem relevant. I don't see anything in my definition that 
prevents one from having two different but identical ADTs. If you think 
there is, imagine whatever words you think would be needed to have that 
effect.

> 2. You cannot do anything with a type otherwise than through its 
> operations. So the definition would be useless without splitting 
> operations into "operations operations" and not "quite operations", which 
> you apparently trying to do.

Definitely. As I mentioned earlier, there is a closed, finite set of 
operations involved in an ADT. There can be other operations that are built 
on the set of operations, but they are definitely not part of the ADT. If 
the set of operations is not closed, then one cannot abstractly reason about 
the ADT, defeating the purpose of the definition. (It also defeats 
reusability, which is rather the point of defining ADTs in the first place.

>> For Ada, this means that an ADT is a private type (possibly tagged) with
>> (usually explicit) primitive operations, and that there are no end-runs 
>> on
>> those primitive operations. All other uses of the ADT are built out of 
>> those
>> primitives.
>
> Why does it follow?
>
> 1. Private type means that parts of the representation is hidden. Your 
> definition is not related to that.

All of the operations need to be explicit and a closed set. If the 
representation is not hidden, that cannot be true. QED. (Yes, my definition 
was sloppy. So what?)

> 2. Primitiveness of an operation is not related either.

If the type is private, the operations have to be declared there, and that 
makes them primitive. (No Ada ADTs outside of an Ada package.)

>> If a type is not private, it cannot be an ADT, as it provides an 
>> unlimited
>> number of other operations that are not described explicitly.
>
> How primitiveness changes that? I still can define new subprograms taking 
> and returning values of the type regardless.

If they're not part of the package, then they are operations that use the 
ADT, but are not part of the ADT. For many programs, most of the code is 
built on ADTs but are not themselves part of any ADT (because they require 
the services of many ADTs - which one does it belong to? Any answer is 
arbitrary).

...
>> With the
>> Wikipedia definition above, every Ada data type is an ADT, since every 
>> type
>> can be described this way (every operation on a numeric type is described 
>> by
>> the Ada Standard, after all, and a client can use nothing else). That's a
>> completely useless definition.
>
> ADT is the semantics it implements. You first have the semantics 
> (mathematical model of the problem space) and then an implementation of.
>
> Non-ADT is ad-hoc semantics deduced from a given representation. You take 
> 'int' from the compiler and then try to figure out if it can be useful for 
> you.
>
> That is the difference.

Based on this definition, almost nothing should be an ADT, because very 
little can be described only by its semantics. Humm, that's actually a true 
statement; probably we are feeling different parts of the elephant and 
describing it very differently. Still, you seem to think of an ADT as a 
constantly increasing (and ad-hoc) set of operations, while I view only the 
operations declared directly with the (private) type as part of the ADT. 
Reasoning ability alone requires a minimum set of operations (but I wouldn't 
want to require that explicitly in a definition lest programmers get tied up 
trying to eliminate excess operations -- not worth the work).

                                    Randy.



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

* Re: Extending a third party tagged type while adding finalization
  2017-12-07 23:22                       ` Randy Brukardt
@ 2017-12-08  9:30                         ` Dmitry A. Kazakov
  2017-12-09  0:17                           ` Randy Brukardt
  0 siblings, 1 reply; 45+ messages in thread
From: Dmitry A. Kazakov @ 2017-12-08  9:30 UTC (permalink / raw)


On 08/12/2017 00:22, Randy Brukardt wrote:
> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
> news:p0auie$h5h$1@gioia.aioe.org...
>> On 07/12/2017 02:13, Randy Brukardt wrote:
>>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>>> news:p07343$1tst$1@gioia.aioe.org...
>>>> On 2017-12-05 22:09, Randy Brukardt wrote:
>>> ...
>>> The above is much too complex. It could be simplified a lot:
>>>
>>> An ADT is a data type (from the perspective of a client of a type)
>>> defined solely by the operations defined for that data type.
> 
> This was a bit sloppy; it should also have required the operations to be
> defined explicitly and as a closed set of operations.

The set cannot closed, most types (and most models they implement) have 
mixed operations. And models do intersect too. This is why multiple 
inheritance is so important.

> Definitely. As I mentioned earlier, there is a closed, finite set of
> operations involved in an ADT.

This just follows from the ADT semantics. It is upfront to the ADT 
definition and implementation. That enforces certain properties on the 
operations implementing it.

The reverse is wrong. You cannot have make it ADT by merely having a 
bunch of operations in the same package.

> There can be other operations that are built
> on the set of operations, but they are definitely not part of the ADT.

How can you tell? To me it is meaningless without considering the 
semantics. If an operation implements some part of the ADT semantics, it 
is of ADT. If it does not then it is an implementation detail and must 
be hidden unless it belongs to some other ADT.

> If
> the set of operations is not closed, then one cannot abstractly reason about
> the ADT, defeating the purpose of the definition. (It also defeats
> reusability, which is rather the point of defining ADTs in the first place.

We reason about ADT implementations. ADT semantics is already defined by 
the model. The models do intersect and interact. It is not closeness you 
probably mean but rather borders between modeled entities. These borders 
are defined during the problem space analysis and enforced by the 
language typing system. Ada is strongly typed, so there is nothing to 
worry about here.

>> 1. Private type means that parts of the representation is hidden. Your
>> definition is not related to that.
> 
> All of the operations need to be explicit and a closed set.
> If the representation is not hidden, that cannot be true.

The representation can exactly match the type semantics, e.g. an 
enumeration type or discrete type:

    type Alarm is (Low, High);
    type Room_Temperature is digits ... range 0.0..30.0;

[If you consider these representations.]

There is nothing wrong in exposing representations telling the problem 
space's truths. Only implementation artifacts need to be hidden and only 
when they expose things breaking the abstraction.

> QED. (Yes, my definition
> was sloppy. So what?)

Sloppy definitions lead to sloppy conclusions ... (:-))

>> 2. Primitiveness of an operation is not related either.
> 
> If the type is private, the operations have to be declared there, and that
> makes them primitive. (No Ada ADTs outside of an Ada package.)

You can declare non-primitive operations at same places. You are trying 
to define a general concept in terms of Ada design artifacts (if not 
design faults).

>>> If a type is not private, it cannot be an ADT, as it provides an
>>> unlimited number of other operations that are not described explicitly.
>>
>> How primitiveness changes that? I still can define new subprograms taking
>> and returning values of the type regardless.
> 
> If they're not part of the package, then they are operations that use the
> ADT, but are not part of the ADT.

Now you are attempting to tie ADT with packages. Why should these be 
related. Aren't types partially defined in a chain of packages and 
completed in some other package ADT?

> For many programs, most of the code is
> built on ADTs but are not themselves part of any ADT (because they require
> the services of many ADTs - which one does it belong to? Any answer is
> arbitrary).

No you want to deny ADT reuse or abstraction. A matrix element can be 
ADT but the matrix and vector cannot because it uses element ADT?

> ...
>>> With the
>>> Wikipedia definition above, every Ada data type is an ADT, since every type
>>> can be described this way (every operation on a numeric type is described by
>>> the Ada Standard, after all, and a client can use nothing else). That's a
>>> completely useless definition.
>>
>> ADT is the semantics it implements. You first have the semantics
>> (mathematical model of the problem space) and then an implementation of.
>>
>> Non-ADT is ad-hoc semantics deduced from a given representation. You take
>> 'int' from the compiler and then try to figure out if it can be useful for
>> you.
>>
>> That is the difference.
> 
> Based on this definition, almost nothing should be an ADT, because very
> little can be described only by its semantics. Humm, that's actually a true
> statement; probably we are feeling different parts of the elephant and
> describing it very differently.

Probably. Things you cannot associate with the semantics are 
implementation aspects. They can be any so long the semantics maintained.

> Still, you seem to think of an ADT as a
> constantly increasing (and ad-hoc) set of operations, while I view only the
> operations declared directly with the (private) type as part of the ADT.

No. The way ADT is implemented does not bother me. Inheritance is a tool 
to implement ADTs. Built-in arrays, records, variant-records is another. 
Subtyping, constraining is a third. A programmer can use any of these in 
any combination in order to implement a type with the required 
semantics. The result is an ADT.

You are right that the interface of an ADT must be clear. This is why 
Ada has means for information hiding. Any aspects irrelevant to the 
semantics of the ADT must be hidden. It is not always possible in Ada 
and I always wished more help to that, especially interfaces for and of 
arrays, record, access, tasks, protected object types, constructors, 
user aggregates etc.

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


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

* Re: Extending a third party tagged type while adding finalization
  2017-12-08  9:30                         ` Dmitry A. Kazakov
@ 2017-12-09  0:17                           ` Randy Brukardt
  2017-12-11  9:03                             ` Dmitry A. Kazakov
  0 siblings, 1 reply; 45+ messages in thread
From: Randy Brukardt @ 2017-12-09  0:17 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:p0dm3g$dgf$1@gioia.aioe.org...
> On 08/12/2017 00:22, Randy Brukardt wrote:
...
>> There can be other operations that are built
>> on the set of operations, but they are definitely not part of the ADT.
>
> How can you tell? To me it is meaningless without considering the 
> semantics. If an operation implements some part of the ADT semantics, it 
> is of ADT. If it does not then it is an implementation detail and must be 
> hidden unless it belongs to some other ADT.

This seems to suggest that you are trying to make everything into an ADT (as 
opposed to just a DT - "Data Type"). The crux of the matter here is the 
"abstract" part - there has to be a consise description of the purpose of 
the type and operations. Something spread all over the place can't have the 
abstract semantics necessary for an ADT.

...
>>> 1. Private type means that parts of the representation is hidden. Your
>>> definition is not related to that.
>>
>> All of the operations need to be explicit and a closed set.
>> If the representation is not hidden, that cannot be true.
>
> The representation can exactly match the type semantics, e.g. an 
> enumeration type or discrete type:
>
>    type Alarm is (Low, High);
>    type Room_Temperature is digits ... range 0.0..30.0;
>
> [If you consider these representations.]
>
> There is nothing wrong in exposing representations telling the problem 
> space's truths. Only implementation artifacts need to be hidden and only 
> when they expose things breaking the abstraction.

The problem here is that you are exposing a lot more than just the fact that 
Room_Temperature is a numeric value with a range. You're also exposing the 
representation details (Size, Alignment, the fact this is a float rather 
than fixed representation), and a large bunch of inherent operations which 
may or may not make sense for this data type (what does "**" mean for a 
temperature, for instance?). The number of ADTs where exactly what Ada gives 
you is correct sensible is essentially zero. Thus, the statement that the 
type of an ADT has to be private.

The types you have above cannot be ADTs (at least not in Ada), since they 
expose many irrelevant implementation details. I use a lot of such types, 
but I wouldn't care to try to give any sort of abstract definition for them.

...
>>> 2. Primitiveness of an operation is not related either.
>>
>> If the type is private, the operations have to be declared there, and 
>> that
>> makes them primitive. (No Ada ADTs outside of an Ada package.)
>
> You can declare non-primitive operations at same places. You are trying to 
> define a general concept in terms of Ada design artifacts (if not design 
> faults).

The purpose of Ada packages was to model ADTs. A package+private 
type+operations=ADT is fundamental to the Ada design.

In any case, if you presume as I do that the type of an ADT has to be 
private, you have little choice but to put the basic operations in the same 
package. And one should not consider operations that can be build out of the 
basic ones as part of the ADT, lest you harm reusability and maintainability 
(the only reasons for writing ADTs in the first place).

>>>> If a type is not private, it cannot be an ADT, as it provides an
>>>> unlimited number of other operations that are not described explicitly.
>>>
>>> How primitiveness changes that? I still can define new subprograms 
>>> taking
>>> and returning values of the type regardless.
>>
>> If they're not part of the package, then they are operations that use the
>> ADT, but are not part of the ADT.
>
> Now you are attempting to tie ADT with packages. Why should these be 
> related. Aren't types partially defined in a chain of packages and 
> completed in some other package ADT?

No, I wouldn't say that. An ADT might be built out of some other types 
(including other ADTs), but pretty much only by composition. The only 
exception would be inheritance of operations from some parent type, and 
those can be thought of as being repeated (implicitly) in the definition of 
the new type.

>> For many programs, most of the code is
>> built on ADTs but are not themselves part of any ADT (because they 
>> require
>> the services of many ADTs - which one does it belong to? Any answer is
>> arbitrary).
>
> No you want to deny ADT reuse or abstraction. A matrix element can be ADT 
> but the matrix and vector cannot because it uses element ADT?

?? Composition of ADTs makes perfect sense. That doesn't make the vector 
operations (having element parameters) part of the element ADT (its clearly 
part of the vector ADT).

But most mixed operations don't clearly belong to one ADT or another. 
They're just things that need to be done. (Indeed, the entire top-level of a 
program tends to be in this category - it's not going to be reusable since 
it is tied to a particular task, it's not going to be commonly used since it 
is the high-level operations for a particular task - and as such, spending 
much time at all figuring out what abstract entities are involved is wasted. 
Just get the job done, spend the effort on the building block parts of the 
system that will be reused.)

...
>> Based on this definition, almost nothing should be an ADT, because very
>> little can be described only by its semantics. Humm, that's actually a 
>> true
>> statement; probably we are feeling different parts of the elephant and
>> describing it very differently.
>
> Probably. Things you cannot associate with the semantics are 
> implementation aspects. They can be any so long the semantics maintained.

I suspect you are trying to describe much more of a system by its semantics 
than I do. As I previously noted, it just isn't worth the effort to figure 
about abstract meanings for things unless they are either very common in a 
system or likely candidates for reuse. There's a lot of stuff that has to be 
done in programs that defies logical explanation, but that's irrelevant --  
one just has to implement something that passes the test, no one cares if it 
is elegant. (It took me a long time to come to grips with this truth.) So 
it's important to realize that one is a lot more productive if one picks 
their spots where to be elegant (where to use an ADT, in this discussion).

...
 > You are right that the interface of an ADT must be clear. This is why
> Ada has means for information hiding. Any aspects irrelevant to the 
> semantics of the ADT must be hidden. It is not always possible in Ada and 
> I always wished more help to that, especially interfaces for and of 
> arrays, record, access, tasks, protected object types, constructors, user 
> aggregates etc.

I suspect that programmers always will want more help at that. Ada 2020 is 
likely to give you some additional help (but not in the generalized manner 
that you are always touting). We're working on user aggregates and literals 
for private types, and probably some other things I've forgotten.

                                   Randy.


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

* Re: Extending a third party tagged type while adding finalization
  2017-12-09  0:17                           ` Randy Brukardt
@ 2017-12-11  9:03                             ` Dmitry A. Kazakov
  2017-12-11 22:42                               ` Randy Brukardt
  2017-12-12 20:08                               ` G. B.
  0 siblings, 2 replies; 45+ messages in thread
From: Dmitry A. Kazakov @ 2017-12-11  9:03 UTC (permalink / raw)


On 2017-12-09 01:17, Randy Brukardt wrote:

>> How can you tell? To me it is meaningless without considering the
>> semantics. If an operation implements some part of the ADT semantics, it
>> is of ADT. If it does not then it is an implementation detail and must be
>> hidden unless it belongs to some other ADT.
> 
> This seems to suggest that you are trying to make everything into an ADT (as
> opposed to just a DT - "Data Type").

Absolutely.

> The crux of the matter here is the
> "abstract" part - there has to be a consise description of the purpose of
> the type and operations.

In the project documentation or else in the developer's head. Don't we 
(Ada community) promote think first approach?

> Something spread all over the place can't have the
> abstract semantics necessary for an ADT.

Semantics can be modular, so can be implementation. If you do not allow 
that, abstractions will be limited to very basic things and the rest 
will remain a "datatype mess".

I see that as a problem many Ada supporters have when they argue against OO.

OO is an attempt to have the design mostly in terms of ADTs. Object 
orientation is thinking in instances of ADTs. Procedural approach is 
falling back to amorphous data as opposed to types and ad-hoc 
subprograms instead of operations/methods.

> ...
>>>> 1. Private type means that parts of the representation is hidden. Your
>>>> definition is not related to that.
>>>
>>> All of the operations need to be explicit and a closed set.
>>> If the representation is not hidden, that cannot be true.
>>
>> The representation can exactly match the type semantics, e.g. an
>> enumeration type or discrete type:
>>
>>     type Alarm is (Low, High);
>>     type Room_Temperature is digits ... range 0.0..30.0;
>>
>> [If you consider these representations.]
>>
>> There is nothing wrong in exposing representations telling the problem
>> space's truths. Only implementation artifacts need to be hidden and only
>> when they expose things breaking the abstraction.
> 
> The problem here is that you are exposing a lot more than just the fact that
> Room_Temperature is a numeric value with a range. You're also exposing the
> representation details (Size, Alignment, the fact this is a float rather
> than fixed representation), and a large bunch of inherent operations which
> may or may not make sense for this data type (what does "**" mean for a
> temperature, for instance?).

I can hide operations I don't want by making them abstract. Regarding 
representation attributes they are ADTs from another domain. Each type 
is a bunch of interfaces. You need an interface of a container element 
in order to have arrays of temperatures. You need an interface to have 
pointers to temperatures. You need an interface to read/write 
temperatures from/to the stream etc.

> The number of ADTs where exactly what Ada gives
> you is correct sensible is essentially zero. Thus, the statement that the
> type of an ADT has to be private.

It need not to be exact. It must be inclusive. Other interfaces that do 
not break the abstraction of interest are OK. There is nothing wrong in 
having Room_Temperature'Input operation.

> The types you have above cannot be ADTs (at least not in Ada), since they
> expose many irrelevant implementation details. I use a lot of such types,
> but I wouldn't care to try to give any sort of abstract definition for them.

You cannot have insulated abstractions and so self-contained ADTs. This 
simply is not how the Universe works. The use of an object depends on 
the point of view. Each type is necessarily an implementation of a 
number of interfaces limited only by the design.

>>> If they're not part of the package, then they are operations that use the
>>> ADT, but are not part of the ADT.
>>
>> Now you are attempting to tie ADT with packages. Why should these be
>> related. Aren't types partially defined in a chain of packages and
>> completed in some other package ADT?
> 
> No, I wouldn't say that. An ADT might be built out of some other types
> (including other ADTs), but pretty much only by composition. The only
> exception would be inheritance of operations from some parent type, and
> those can be thought of as being repeated (implicitly) in the definition of
> the new type.

You also have generic instances (parametrized types) and type cloning 
(type X is new Y;)

>> No you want to deny ADT reuse or abstraction. A matrix element can be ADT
>> but the matrix and vector cannot because it uses element ADT?
> 
> ?? Composition of ADTs makes perfect sense. That doesn't make the vector
> operations (having element parameters) part of the element ADT (its clearly
> part of the vector ADT).

> But most mixed operations don't clearly belong to one ADT or another.
> They're just things that need to be done. (Indeed, the entire top-level of a
> program tends to be in this category - it's not going to be reusable since
> it is tied to a particular task, it's not going to be commonly used since it
> is the high-level operations for a particular task - and as such, spending
> much time at all figuring out what abstract entities are involved is wasted.
> Just get the job done, spend the effort on the building block parts of the
> system that will be reused.)

See, you mow all type abstraction running all the rest basically 
weakly-/untyped. Why bother with ADTs if you don't let them grow?

> ...
>>> Based on this definition, almost nothing should be an ADT, because very
>>> little can be described only by its semantics. Humm, that's actually a
>>> true
>>> statement; probably we are feeling different parts of the elephant and
>>> describing it very differently.
>>
>> Probably. Things you cannot associate with the semantics are
>> implementation aspects. They can be any so long the semantics maintained.
> 
> I suspect you are trying to describe much more of a system by its semantics
> than I do. As I previously noted, it just isn't worth the effort to figure
> about abstract meanings for things unless they are either very common in a
> system or likely candidates for reuse. There's a lot of stuff that has to be
> done in programs that defies logical explanation, but that's irrelevant --
> one just has to implement something that passes the test, no one cares if it
> is elegant. (It took me a long time to come to grips with this truth.) So
> it's important to realize that one is a lot more productive if one picks
> their spots where to be elegant (where to use an ADT, in this discussion).

Yes, this is our core disagreement. I want everything designed in ADTs 
with a stated purpose.

> We're working on user aggregates and literals
> for private types, and probably some other things I've forgotten.

That is great news, really.

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

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

* Re: Extending a third party tagged type while adding finalization
  2017-12-11  9:03                             ` Dmitry A. Kazakov
@ 2017-12-11 22:42                               ` Randy Brukardt
  2017-12-12 16:11                                 ` AdaMagica
  2017-12-12 20:08                               ` G. B.
  1 sibling, 1 reply; 45+ messages in thread
From: Randy Brukardt @ 2017-12-11 22:42 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:p0lhk4$1okm$1@gioia.aioe.org...
> On 2017-12-09 01:17, Randy Brukardt wrote:

I was going to write a longer response, but I think we understand each 
other's positions and we're unlikely to change each other's mind by further 
talk. (And no one else seems to be reading this...) So just a closing 
summary.
...
>> But most mixed operations don't clearly belong to one ADT or another.
>> They're just things that need to be done. (Indeed, the entire top-level 
>> of a
>> program tends to be in this category - it's not going to be reusable 
>> since
>> it is tied to a particular task, it's not going to be commonly used since 
>> it
>> is the high-level operations for a particular task - and as such, 
>> spending
>> much time at all figuring out what abstract entities are involved is 
>> wasted.
>> Just get the job done, spend the effort on the building block parts of 
>> the
>> system that will be reused.)
>
> See, you mow all type abstraction running all the rest basically 
> weakly-/untyped. Why bother with ADTs if you don't let them grow?

Changing ADTs can be very difficult. (That's especially true for full OOP 
designs.) And it is highly unlikely that one will get the initial design 
correct. So in the interest of getting the maximum work done for the minimum 
effort, it's necessary to draw a line at a point where the advantages of 
ADTs are outweighed by their disadvantages. And they have clear 
disadvantages for code that isn't well-understood or experimental or is a 
pure one-off. (That's probably 80% of the code I write.)

> ...
>>>> Based on this definition, almost nothing should be an ADT, because very
>>>> little can be described only by its semantics. Humm, that's actually a
>>>> true
>>>> statement; probably we are feeling different parts of the elephant and
>>>> describing it very differently.
>>>
>>> Probably. Things you cannot associate with the semantics are
>>> implementation aspects. They can be any so long the semantics 
>>> maintained.
>>
>> I suspect you are trying to describe much more of a system by its 
>> semantics
>> than I do. As I previously noted, it just isn't worth the effort to 
>> figure
>> about abstract meanings for things unless they are either very common in 
>> a
>> system or likely candidates for reuse. There's a lot of stuff that has to 
>> be
>> done in programs that defies logical explanation, but that's 
>> irrelevant --
>> one just has to implement something that passes the test, no one cares if 
>> it
>> is elegant. (It took me a long time to come to grips with this truth.) So
>> it's important to realize that one is a lot more productive if one picks
>> their spots where to be elegant (where to use an ADT, in this 
>> discussion).
>
> Yes, this is our core disagreement. I want everything designed in ADTs 
> with a stated purpose.

I don't think that is practical -- certainly not by me. I don't think 
abstractly enough to be able to come up with abstract definitions for a lot 
of things easily. It takes a lot of effort (and time and money), and that 
effort isn't well-spent for things that aren't ever going to be reused, that 
aren't a large part of a program, and often are rather illogical (for 
instance, some of the rules of a real language like Ada). One has to be 
careful to err on the side of over-designing rather than under-designing, 
but trying to abstract everything would double the amount of effort it takes 
(for me, YMMV) to get it built. And re-factoring is always an option if it 
turns out that an ADT would actually have been useful.

                                               Randy.
 



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

* Re: Extending a third party tagged type while adding finalization
  2017-12-11 22:42                               ` Randy Brukardt
@ 2017-12-12 16:11                                 ` AdaMagica
  0 siblings, 0 replies; 45+ messages in thread
From: AdaMagica @ 2017-12-12 16:11 UTC (permalink / raw)


Am Montag, 11. Dezember 2017 23:42:03 UTC+1 schrieb Randy Brukardt:
> And no one else seems to be reading this...

That's not true, I'm following with awe your endless discussions (not only this one) which never lead to a conclusion. I often have problems following Dmitry's posts when he uses non-Ada terms or Ada terms with another meaning.

Now for ADTs.

I'm thinking of the millions lines of code embedded helicopter code that I rehosted for a flight simulator. (Btw - only very few lines of code had to be touched because of hardware dependence, mostly little vs. big endian, and because of compiler dependence, all ill-used Ada code).

How could the main subprogram have been an ADT? It was an infinite loop running with 20 ms cycle time of which it could use only 5 ms, reading and handling the different simulator states (there were many: init, running, freeze, repositioning, snapshot reload etc.) manipulated by the flight instructor.

External power supply (starting avionics elaboration and tasks, terminating and restarting with power loss) was an ADT, but to my dismay developed into chaos because of the many different simulator states.

Another ADT was the tasking management (Ada's preemptive scheduling had to be adapted to the above 5 ms and 15 ms sleeping with only faint intrusion into the original tasks). This indeed was a very nice small ADT I'm still fond of.

There were a lot of other ADTs and non-ADTs. So I'm more on Randy's side.


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

* Re: Extending a third party tagged type while adding finalization
  2017-12-11  9:03                             ` Dmitry A. Kazakov
  2017-12-11 22:42                               ` Randy Brukardt
@ 2017-12-12 20:08                               ` G. B.
  2017-12-12 20:32                                 ` Dmitry A. Kazakov
  1 sibling, 1 reply; 45+ messages in thread
From: G. B. @ 2017-12-12 20:08 UTC (permalink / raw)


Dmitry A. Kazakov <mailbox@dmitry-kazakov.de> wrote:
>
> Why bother with ADTs if you don't let them grow?

Some plants grow to their natural size and yet
they are useful for our purposes.

> I want everything designed in ADTs 
> with a stated purpose.

This renders distinct units of design, below and
above the level of “ADT”, as universally useless.
I never trust universal statements.

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

* Re: Extending a third party tagged type while adding finalization
  2017-12-12 20:08                               ` G. B.
@ 2017-12-12 20:32                                 ` Dmitry A. Kazakov
  0 siblings, 0 replies; 45+ messages in thread
From: Dmitry A. Kazakov @ 2017-12-12 20:32 UTC (permalink / raw)


On 2017-12-12 21:08, G. B. wrote:
> Dmitry A. Kazakov <mailbox@dmitry-kazakov.de> wrote:

>> I want everything designed in ADTs
>> with a stated purpose.
> 
> This renders distinct units of design, below and
> above the level of “ADT”, as universally useless.

Right, design without purpose is no design.

> I never trust universal statements.

BTW, differently to my statement yours is universal indeed.

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

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

end of thread, other threads:[~2017-12-12 20:32 UTC | newest]

Thread overview: 45+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-11-22 12:43 Extending a third party tagged type while adding finalization Jere
2017-11-22 16:42 ` AdaMagica
2017-11-26 17:33   ` Jere
2017-11-26 18:15     ` Dmitry A. Kazakov
2017-11-26 19:31       ` Jere
2017-11-27  9:46     ` AdaMagica
2017-11-27 12:56       ` Jere
2017-11-27 15:00         ` AdaMagica
2017-11-27 16:38           ` Jere
2017-11-27 18:37             ` AdaMagica
2017-11-27 19:53               ` Jere
2017-11-28 11:48                 ` AdaMagica
2017-12-03  2:22                   ` Jere
2017-12-03 21:53               ` Robert Eachus
2017-12-04  7:58                 ` Dmitry A. Kazakov
2017-12-04 14:59                   ` Robert Eachus
2017-12-04 15:39                     ` Dmitry A. Kazakov
2017-11-27 18:10     ` Shark8
2017-11-27 19:56       ` Jere
2017-11-28  1:55       ` Randy Brukardt
2017-12-03  2:47         ` Jere
2017-12-03  9:29           ` Dmitry A. Kazakov
2017-12-03 15:10             ` AdaMagica
2017-12-03 16:39               ` Dmitry A. Kazakov
2017-12-03 19:34             ` AdaMagica
2017-12-03 19:41               ` Dmitry A. Kazakov
2017-12-04 12:38                 ` AdaMagica
2017-12-04 13:19                   ` AdaMagica
2017-12-04 13:55                     ` Dmitry A. Kazakov
2017-12-04 15:44                       ` AdaMagica
2017-12-04 16:19                         ` Dmitry A. Kazakov
2017-12-04 20:54           ` Randy Brukardt
2017-12-04 21:02             ` Dmitry A. Kazakov
2017-12-05 21:09               ` Randy Brukardt
2017-12-05 21:29                 ` Dmitry A. Kazakov
2017-12-07  1:13                   ` Randy Brukardt
2017-12-07  8:36                     ` Dmitry A. Kazakov
2017-12-07 23:22                       ` Randy Brukardt
2017-12-08  9:30                         ` Dmitry A. Kazakov
2017-12-09  0:17                           ` Randy Brukardt
2017-12-11  9:03                             ` Dmitry A. Kazakov
2017-12-11 22:42                               ` Randy Brukardt
2017-12-12 16:11                                 ` AdaMagica
2017-12-12 20:08                               ` G. B.
2017-12-12 20:32                                 ` Dmitry A. Kazakov

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