* 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