* Re: Constructors/Destructors in Ada95 @ 2000-10-29 22:51 rwilson007007 2000-10-30 4:03 ` Ray Blaak 2000-10-30 12:13 ` Marin David Condic 0 siblings, 2 replies; 35+ messages in thread From: rwilson007007 @ 2000-10-29 22:51 UTC (permalink / raw) Greetings, One thing that has struck me (vis-a-vis C++ versus Ada classes) is that, unlike in Ada, the data structure associated with a C++ class is never explicitly defined by the language - that is, afaik, the compiler can choose whatever underlying represenation for the class it wishes. If I desired to mimic the C++ notion of classes in Ada, I would be tempted to encapsulate a tagged record instance within a generic package (the formal parameters of which act as constructor arguments and the elaboration of which acts as a constructor). This both hides the ada-record data representation and renders the familiar C++ "object_ref.method_name" style of method invocation syntax. That is, rather than being tempted to overload Ada's assignment operator, I would prefer to replace: "My_Object = new My_Class_Name (Argument_List)" in C++ with "package My_Object is new My_Class_Name.Instance (Argument_List)" in Ada (see example below...). ** Could one of the wise participants in this discussion please instruct me as to whether or not there is some fundamental problem or limitation with Ada generics that makes this an unsensible approach?** --Richard Wilson -- BRIEF EXAMPLE: -- SPEC -- definition of class which inherits from a controlled object with Some_Base_Class; -- limited controlled with Attribute_1_Class; with Attribute_2_Class; with Attribute_3_Class; package Some_Class is type Object is new Some_Base_Class.Object with record Attribute_1 : Attribute_1_Class.Object; Attribute_2 : Attribute_2_Class.Object; Attribute_3 : Attribute_3_Class.Object; end record; type Ref is access all Object'Class; procedure Method_1 (This : Ref; Parameter_1 : in Integer); procedure Method_2 (This : Ref; Returns : out Attribute_1_Class.Object); generic Attribute_1 : Attribute_1_Class.Object := Attribute_1_Class.Default; Attribute_2 : Attribute_2_Class.Object; Attribute_3 : Attribute_3_Class.Object; package Instance is procedure Method_1 (Parameter_1 : Integer); procedure Method_2 (Returns : out Attribute_1_Class.Object); -- note that "This : Ref" argument is not necessary at this scope function Copy return Ref; -- returns deep copy procedure Destroy; -- object is created when Instance first instantiated -- if Destroy has been invoked, the instance of Instance is still -- in scope, and and one wishes to use the object again -- then one must invoke: procedure Resurrect (Attribute_1 : in Attribute_1_Class.Object := Attribute_1_Class.Default; Attribute_2 : in Attribute_2_Class.Object; Attribute_3 : in Attribute_3_Class.Object); end Instance; private procedure Initialize (This : in out Object); procedure Finalize (This : in out Object); end Some_Class; -- BODY package body Some_Class is procedure Method_1 (This : Ref; Parameter_1 :in Integer) is begin This.Attribute_2.Ticks := This.Attribute_2.Ticks + Parameter_1; end Method_1; procedure Method_2 (This : Ref; Returns : out Attribute_1_Class.Object) is begin return This.Attribute_2; end Method_2; package body Instance is This : aliased Object; procedure Method_1 (Parameter_1 : in Integer) is begin Some_Class.Method_1 (This => This, Parameter_1 => Parameter_1); end Method_1; -- etc... begin This := new Object; This.Attribute_1 := Attribute_1; This.Attribute_2 := Attribute_2; This.Attribute_3 := Attribute_3; -- and so on... end Instance; end Some_Class; -- CLIENT CODE EXAMPLE declare Init_Param_0 : Attribute_2_Class.Object := (Ticks => 23, others => 0); Init_Param_1 : Attribute_3_Class.Object := (others => ''); My_Copy : Some_Class.Ref; -- construct my object package My_Object is new Some_Class.Instance (Attribute_2 => Init_Param_0, Attribute_3 => Init_Param_1); begin My_Object.Method_1 (Parameter_1 => 0); My_Object.Method_2 (Returns => Init_Param_0); My_Copy := My_Object.Copy_To; Some_Class.Method_1 (This => My_Copy, Parameter_1 => 0); My_Object.Destroy; My_Object.Reconstruct (Attribute_2 => Init_Param_0, Attribute_3 => Init_Param_1); My_Object.Copy (From => My_Copy); end; Sent via Deja.com http://www.deja.com/ Before you buy. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Constructors/Destructors in Ada95 2000-10-29 22:51 Constructors/Destructors in Ada95 rwilson007007 @ 2000-10-30 4:03 ` Ray Blaak 2000-10-30 12:13 ` Marin David Condic 1 sibling, 0 replies; 35+ messages in thread From: Ray Blaak @ 2000-10-30 4:03 UTC (permalink / raw) rwilson007007@my-deja.com writes: > If I desired to mimic the C++ notion of classes in Ada, I would be tempted > to encapsulate a tagged record instance within a generic package [...] > That is, rather than being tempted to overload Ada's assignment > operator, I would prefer to replace: > "My_Object = new My_Class_Name (Argument_List)" in C++ > with > "package My_Object is new My_Class_Name.Instance (Argument_List)" > in Ada (see example below...). The main problem with this approach is that packages are not first class objects in Ada. They do not have addresses, cannot be passed as parameters or compared to each other, etc. Packages are static namespaces. -- Cheers, The Rhythm is around me, The Rhythm has control. Ray Blaak The Rhythm is inside me, blaak@infomatch.com The Rhythm has my soul. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Constructors/Destructors in Ada95 2000-10-29 22:51 Constructors/Destructors in Ada95 rwilson007007 2000-10-30 4:03 ` Ray Blaak @ 2000-10-30 12:13 ` Marin David Condic 2000-10-30 16:39 ` Randy Brukardt 1 sibling, 1 reply; 35+ messages in thread From: Marin David Condic @ 2000-10-30 12:13 UTC (permalink / raw) To: rwilson007007 rwilson007007@my-deja.com wrote: > That is, rather than being tempted to overload Ada's assignment > operator, I would prefer to replace: > "My_Object = new My_Class_Name (Argument_List)" in C++ > with > "package My_Object is new My_Class_Name.Instance (Argument_List)" > in Ada (see example below...). > > ** Could one of the wise participants in this discussion please > instruct me as to whether or not there is some fundamental problem or > limitation with Ada generics that makes this an unsensible approach?** Very clever! However, at least one issue would be raised. A generic instanciation of My_Class_Name would result in a duplication of the object code associated with My_Class_Name for every object of that class you declare. This is at least true of every Ada compiler of which I am aware. I don't know if anybody supports code sharing for generics on a currently marketed Ada95 compiler. This technique could thus prove to be expensive for classes where lots of objects are declared. Also, there could be some time penalty in runtime instanciation that may be significant for classes with lots of objects associated with them. MDC -- ====================================================================== Marin David Condic - Quadrus Corporation - http://www.quadruscorp.com/ Send Replies To: m c o n d i c @ q u a d r u s c o r p . c o m Visit my web site at: http://www.mcondic.com/ "Giving money and power to Government is like giving whiskey and car keys to teenage boys." -- P. J. O'Rourke ====================================================================== ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Constructors/Destructors in Ada95 2000-10-30 12:13 ` Marin David Condic @ 2000-10-30 16:39 ` Randy Brukardt 0 siblings, 0 replies; 35+ messages in thread From: Randy Brukardt @ 2000-10-30 16:39 UTC (permalink / raw) Marin David Condic wrote in message <39FD65FB.388A05D0@acm.org>... >rwilson007007@my-deja.com wrote: > >Very clever! However, at least one issue would be raised. A generic >instanciation of My_Class_Name would result in a duplication of the object >code associated with My_Class_Name for every object of that class you >declare. This is at least true of every Ada compiler of which I am aware. >I don't know if anybody supports code sharing for generics on a currently >marketed Ada95 compiler. Janus/Ada 95 still uses "universal" code sharing for generics. There is only one copy of the code for each generic unit; the instantiation provides parameters. I believe that there are other compilers that allow partial sharing in limited instances. Truth in advertising dept.: Janus/Ada 95 is not a complete implementation of Ada 95 (a few parts are missing; notably to this discussion, generic formal derived types). I don't know if there are any reasons why our implementation cannot implement those part not yet implemented (haven't found any yet, but...) I am a primary author of that compiler, and still owrk at rrsoftware. (Our web site is www.rrsoftware.com, if you care). Randy Brukardt. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Constructors/Destructors in Ada95 @ 2000-10-18 0:00 Francois Godme 2000-10-19 0:00 ` Marin David Condic ` (2 more replies) 0 siblings, 3 replies; 35+ messages in thread From: Francois Godme @ 2000-10-18 0:00 UTC (permalink / raw) Hi all, Where can I find articles, papers, or posted messages explaining me the reasons for the lack of support for Constructors/Destructors directly in the language. I have heard that, in 1995, Tucker Taft on c.l.a posted several messages on this very subject. I went to www.deja.com but they say that temporarily it is not possible to consult archives past 1999. Is there an Ada web site which archives our group? Thanks. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Constructors/Destructors in Ada95 2000-10-18 0:00 Francois Godme @ 2000-10-19 0:00 ` Marin David Condic 2000-10-19 0:00 ` tmoran 2000-10-19 0:00 ` Ted Dennison 2 siblings, 0 replies; 35+ messages in thread From: Marin David Condic @ 2000-10-19 0:00 UTC (permalink / raw) You sort of have the means to get there with Ada.Finalization. Somewhere between Initialize/Finalize/Adjust and other normal language features, you have all the same capabilities of C++'s Constructors/Destructors. I've got some code comparing the two language's mechanisms on my web page. See: http://www.mcondic.com/ and look for The C++ To Ada Translation Page. MDC Francois Godme wrote: > Hi all, > > Where can I find articles, papers, or posted messages explaining me the > reasons for the lack of support for Constructors/Destructors directly in > the language. I have heard that, in 1995, Tucker Taft on c.l.a posted > several messages on this very subject. > > I went to www.deja.com but they say that temporarily it is not possible > to consult archives past 1999. Is there an Ada web site which archives > our group? > > Thanks. -- ====================================================================== Marin David Condic - Quadrus Corporation - http://www.quadruscorp.com/ Send Replies To: m c o n d i c @ q u a d r u s c o r p . c o m Visit my web site at: http://www.mcondic.com/ "Giving money and power to Government is like giving whiskey and car keys to teenage boys." -- P. J. O'Rourke ====================================================================== ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Constructors/Destructors in Ada95 2000-10-18 0:00 Francois Godme 2000-10-19 0:00 ` Marin David Condic @ 2000-10-19 0:00 ` tmoran 2000-10-19 0:00 ` Francois Godme 2000-10-19 0:00 ` Ted Dennison 2 siblings, 1 reply; 35+ messages in thread From: tmoran @ 2000-10-19 0:00 UTC (permalink / raw) > lack of support for Constructors/Destructors directly in the language. What do you feel missing from Ada.Finalization? ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Constructors/Destructors in Ada95 2000-10-19 0:00 ` tmoran @ 2000-10-19 0:00 ` Francois Godme 2000-10-19 0:00 ` Ted Dennison ` (2 more replies) 0 siblings, 3 replies; 35+ messages in thread From: Francois Godme @ 2000-10-19 0:00 UTC (permalink / raw) tmoran@bix.com a �crit : > > lack of support for Constructors/Destructors directly in the language. > What do you feel missing from Ada.Finalization? No one can give me pointers to the true sources? I did not want to start arguing over this question in a newsgroup. My English output flow is not sufficient to sustain long debates. To Ted Dennison, I will say that before I dared to go out on the net, I looked at my in-house documentation. That is the one you can find with the gnat rpms for Linux made by J�ergen Pfeiffer (arm, rationale and Ada style guide). This WHY question is the exception to the rule that every WHY question has an answer in the rationale. grep -il constructor /usr/share/ada/html/rat95html-1.07/* /usr/share/ada/html/rat95html-1.07/rat95-p3-a.html /usr/share/ada/html/rat95html-1.07/rat95-p3-g.html Two non relevant answers. $ grep -il destructor /usr/share/ada/html/rat95html-1.07/* No answer at all. To Marin David Condic, I will say that I went to his web site and that his constructor does not respect the Ada style guide which states: "Avoid declaring a constructor as a primitive abstract operation." Constructors are a pain to inherit. To Tom Moran, I will say that the problem in the Ada.Finalization package is the Initialize procedure. The procedures Adjust and Finalize do not cause any problems. But the Initialize procedure does not respect the Ada style guide for the same reason as above. The Initialize procedure is inherited. And worst, besides the object itself to initialize, there are no other parameters passed to initialize the object. It is like if in C++, all classes were forced to have a default constructor and the instances were first initialized to useless values. That's why the Ada style guide goes on to state: "Consider splitting the initialization and construction of an object." ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Constructors/Destructors in Ada95 2000-10-19 0:00 ` Francois Godme @ 2000-10-19 0:00 ` Ted Dennison 2000-10-20 0:00 ` Tucker Taft 2000-10-22 0:00 ` rwilson007007 2 siblings, 0 replies; 35+ messages in thread From: Ted Dennison @ 2000-10-19 0:00 UTC (permalink / raw) In article <39EF5431.BF4CD793@bigfoot.com>, Francois Godme <fgodme@bigfoot.com> wrote: > This WHY question is the exception to the rule that every WHY question > has an answer in the rationale. > > grep -il constructor /usr/share/ada/html/rat95html-1.07/* > /usr/share/ada/html/rat95html-1.07/rat95-p3-a.html > /usr/share/ada/html/rat95html-1.07/rat95-p3-g.html > > Two non relevant answers. > > $ grep -il destructor /usr/share/ada/html/rat95html-1.07/* > > No answer at all. There is an entire section on this topic at http://www.adaic.org/standards/95rat/RAThtml/rat95-p2-7.html#4 . You probably didn't find it because the proper Ada terms are "Initilization" and "Finalization", not "Construction" and "Destruction". However, I will admit that it doesn't say much about *why* the package approach was chosen over other possible approaches to the same problem. The best I see in there is: --- A number of different approaches were considered and rejected during the evolution of Ada 95. The final solution has the merit of allowing user-defined assignment and also solves the problem of returning limited types mentioned in the previous section. --- Its possible the bit "mentioned in the previous section" will shed some more light on the issue, but I doubt it. -- T.E.D. http://www.telepath.com/~dennison/Ted/TED.html Sent via Deja.com http://www.deja.com/ Before you buy. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Constructors/Destructors in Ada95 2000-10-19 0:00 ` Francois Godme 2000-10-19 0:00 ` Ted Dennison @ 2000-10-20 0:00 ` Tucker Taft 2000-10-20 0:00 ` Francois Godme 2000-10-23 0:00 ` Francois Godme 2000-10-22 0:00 ` rwilson007007 2 siblings, 2 replies; 35+ messages in thread From: Tucker Taft @ 2000-10-20 0:00 UTC (permalink / raw) Francois Godme wrote: > ... > > To Tom Moran, I will say that the problem in the Ada.Finalization package > is the Initialize procedure. It is a mistake to think that the Initialize procedure represents Ada's "constructor" feature. As you recognize below, Initialize is the rough equivalent of the default constructor. For any other kind of constructor, you simply write a function, or procedure with an [in] out parameter. Ada also has a builtin constructor to simplify the creation of these user-defined constructors, namely an aggregate (array, record, or record extension). This is available for non-limited types, in places where the type is visible (e.g. inside the package where it is declared). An aggregate constructor can be combined with dynamic storage allocation, via an initialized allocator. For (inherently) limited types, non-default construction must be done essentially one component at a time, even when inside the package where the type is defined. Of course, from outside the package, an appropriate procedure would be called to invoke the user-chosen construction operation, and that procedure would take care of the appropriate component-by- component actions. > > The procedures Adjust and Finalize do not cause any problems. But the > Initialize procedure does not respect the Ada style guide for the same > reason as above. The Initialize procedure is inherited. And worst, besides > the object itself to initialize, there are no other parameters passed to > initialize the object. It is like if in C++, all classes were forced to > have a default constructor and the instances were first initialized to > useless values. Initialize is exactly the part of the default constructor, over and above the default initialization specified within the type declaration itself. If the type extension adds more components that have default initialization, these default initializations will occur, even if Initialize is inherited. In fact, I would generally recommend that programmers minimize the use of Initialize, if they can do it all with per-component default initialization. But the key point is not to think of "Initialize" as a general purpose constructor. It is simply the default "constructor" (and really only part of that, given the per-component defaults that are applied first). "Regular" functions and procedures are used to do any other "construction." > > That's why the Ada style guide goes on to state: "Consider splitting the > initialization and construction of an object." They should probably say consider splitting *default* initialization and *explicit* construction. This is only really *necessary* for limited types. For non-limited types, using a function to initialize the object upon declaration/dynamic allocation is quite appropriate. -- -Tucker Taft stt@averstar.com http://www.averstar.com/~stt/ Technical Director, Commercial Division, AverStar (formerly Intermetrics) (http://www.averstar.com/services/IT_consulting.html) Burlington, MA USA ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Constructors/Destructors in Ada95 2000-10-20 0:00 ` Tucker Taft @ 2000-10-20 0:00 ` Francois Godme 2000-10-21 0:00 ` Marin David Condic 2000-10-23 0:00 ` Francois Godme 1 sibling, 1 reply; 35+ messages in thread From: Francois Godme @ 2000-10-20 0:00 UTC (permalink / raw) Tucker Taft a �crit : > It is a mistake to think that the Initialize procedure > represents Ada's "constructor" feature. As you recognize > below, Initialize is the rough equivalent of the default > constructor. For any other kind of constructor, you simply > write a function, or procedure with an [in] out parameter. > Ada also has a builtin constructor to simplify the > creation of these user-defined constructors, namely an aggregate > (array, record, or record extension). This is available > for non-limited types, in places where the type is > visible (e.g. inside the package where it is declared). > > An aggregate constructor can be combined with dynamic > storage allocation, via an initialized allocator. > Record aggregates are neat but can only be used in a white box approach on non-limited types. True, non-limited types can be initialized by functions but you have to be careful to not make these functions primitive operations. By using a 'class attribute on the return parameter type for example. > For (inherently) limited types, non-default construction must be > done essentially one component at a time, even when inside > the package where the type is defined. Of course, from outside > the package, an appropriate procedure would be called to > invoke the user-chosen construction operation, and that > procedure would take care of the appropriate component-by- > component actions. > Yes, but the drawback is that instances of limited types cannot be declared constant when they should be. In C++, instances of classes with private operator= and private operator== can be constant. > Initialize is exactly the part of the default constructor, > over and above the default initialization specified within > the type declaration itself. If the type extension adds > more components that have default initialization, these > default initializations will occur, even if Initialize is > inherited. In fact, I would generally recommend that > programmers minimize the use of Initialize, if they can > do it all with per-component default initialization. > Yes, they serve the same purpose with almost the same power. Constructors in C++ have another feature unknown in Ada which allows the creation of constant member attributes. It applies to any type. Not to a limited set of types which can be used as record discriminants. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Constructors/Destructors in Ada95 2000-10-20 0:00 ` Francois Godme @ 2000-10-21 0:00 ` Marin David Condic 0 siblings, 0 replies; 35+ messages in thread From: Marin David Condic @ 2000-10-21 0:00 UTC (permalink / raw) Remember that Ada is not C++. You can pretty much get the same net effect of constructors and destructors in Ada - but not in exactly the same way. So you change the model instead. Since Ada doesn't treat assignment the same way as C++ and you don't have the same parameter features, you've got to work with what Ada does provide and try not to make it look exactly like C++. The job does get done and, IMHO, it is a lot less semantically messy when done in Ada as opposed to C++. MDC Francois Godme wrote: > Yes, they serve the same purpose with almost the same power. Constructors in > C++ have another feature unknown in Ada which allows the creation of constant > member attributes. It applies to any type. Not to a limited set of types which > can be used as record discriminants. -- ====================================================================== Marin David Condic - Quadrus Corporation - http://www.quadruscorp.com/ Send Replies To: m c o n d i c @ q u a d r u s c o r p . c o m Visit my web site at: http://www.mcondic.com/ "Giving money and power to Government is like giving whiskey and car keys to teenage boys." -- P. J. O'Rourke ====================================================================== ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Constructors/Destructors in Ada95 2000-10-20 0:00 ` Tucker Taft 2000-10-20 0:00 ` Francois Godme @ 2000-10-23 0:00 ` Francois Godme 2000-10-24 0:00 ` Ray Blaak 1 sibling, 1 reply; 35+ messages in thread From: Francois Godme @ 2000-10-23 0:00 UTC (permalink / raw) I would like to add some other arguments not yet expressed: * against the non-primitive procedures used as constructors of limited instances like in Tucker Taft's proposal, * against the Adjust procedure and * against the Finalize procedure. I. Non-primitive procedures used as constructors of limited instances: As limited instances can't be initialized with record aggregates, it is possible to write code which forgets to initialize all record fields. It was already the case in Ada83 but only in the horizontal plane. With procedures, it can now get wrong in the vertical plane along the class hierarchy if one forgot to call one of the initializing procedures of its immediate super-class. Programmers have also to remember to call the super-class procedure first as a precaution before initializing extension record fields. Nothing insurmountable I admit. If the language had constructors, the compiler could warn me when I forgot something in the horizontal or the vertical plane. This will increase safety. This doesn't apply to non-limited types if they are initialized only with aggregates and functions. No procedures. II.The Adjust procedure: Efficiency concerns may be raised against the sequence: Finalize (Target); shallow copy Source into Target; Adjust (Target);. In the Adjust procedure, control is given to perform, for instance, a deep copy of Source into Target. One can easily devise situations where Finalize of Target will have to deallocate memory which will be immediately needed and reallocated by Adjust of Target. III. The Finalize procedure: The programmers are responsible in the Finalize procedure to call last the immediate super-class Finalize procedure. As the notion of immediate super-class does not exist in the language, it is not possible to write code that will always call the Finalize procedure of the immediate super-class. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Constructors/Destructors in Ada95 2000-10-23 0:00 ` Francois Godme @ 2000-10-24 0:00 ` Ray Blaak 2000-10-25 0:00 ` Francois Godme ` (2 more replies) 0 siblings, 3 replies; 35+ messages in thread From: Ray Blaak @ 2000-10-24 0:00 UTC (permalink / raw) Francois Godme <fgodme@bigfoot.com> writes: > I. Non-primitive procedures used as constructors of limited instances: As > limited instances can't be initialized with record aggregates, it is possible > to write code which forgets to initialize all record fields. Forgetting to initialize a field is equivalent to using a default constructor, no? In that case the Initialize routine can cover it. If not field is not a tagged type, either a default component assignment can cover it, or if limited, the compiler should flag an error that the item is not created. I do grant you, however, that C++'s constructors are nice for forcing an item to be created in only valid ways. > II.The Adjust procedure: Efficiency concerns may be raised against the > sequence: Finalize (Target); shallow copy Source into Target; Adjust > (Target);. I really would like to be able to do: procedure ":="(target : in out T; source : in T); so as to have complete control over what is happening. I vaguely recall some rationale from the Ada 9X discussions for why user-defined assignment per se was not incorporated. Does anyone remember? > III. The Finalize procedure: > The programmers are responsible in the Finalize procedure to call last the > immediate super-class Finalize procedure. As the notion of immediate > super-class does not exist in the language, it is not possible to write code > that will always call the Finalize procedure of the immediate super-class. Not just in Ada. This bug has bitten me in C++ too often during redesign times. Java's "super" and Delphi's "inherited" keywords neatly make this issue go away. Anyone know of a reason why "super" would not be a good idea for Ada 0X? -- Cheers, The Rhythm is around me, The Rhythm has control. Ray Blaak The Rhythm is inside me, blaak@infomatch.com The Rhythm has my soul. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Constructors/Destructors in Ada95 2000-10-24 0:00 ` Ray Blaak @ 2000-10-25 0:00 ` Francois Godme 2000-10-25 0:00 ` Marin David Condic 2000-10-27 18:11 ` Francois Godme 2 siblings, 0 replies; 35+ messages in thread From: Francois Godme @ 2000-10-25 0:00 UTC (permalink / raw) Ray Blaak a �crit : > > I really would like to be able to do: > > procedure ":="(target : in out T; source : in T); > > so as to have complete control over what is happening. I vaguely recall some > rationale from the Ada 9X discussions for why user-defined assignment per se > was not incorporated. Does anyone remember? > An alternative would be inside Ada.Finalization procedure Deep_Copy (Source : access Controlled; Target : access Controlled); procedure Shallow_Copy (Source : in Controlled'Class; Target : out Controlled'Class); Deep_Copy is an overridible primitive whose default implementation is to call Shallow_Copy to copy Source into Target if Source and Target are different access values and to do nothing otherwise. Shallow_Copy is a class-wide procedure provided by the Ada run-time which avoids to fall into infinite recursion when writing "Target.all := Source.all;". Instead, one writes "Shallow_Copy (Source.all, Target.all);". ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Constructors/Destructors in Ada95 2000-10-24 0:00 ` Ray Blaak 2000-10-25 0:00 ` Francois Godme @ 2000-10-25 0:00 ` Marin David Condic 2000-10-25 0:00 ` dmitry6243 2000-10-27 7:12 ` Ray Blaak 2000-10-27 18:11 ` Francois Godme 2 siblings, 2 replies; 35+ messages in thread From: Marin David Condic @ 2000-10-25 0:00 UTC (permalink / raw) Ray Blaak wrote: > I really would like to be able to do: > > procedure ":="(target : in out T; source : in T); > > so as to have complete control over what is happening. I vaguely recall some > rationale from the Ada 9X discussions for why user-defined assignment per se > was not incorporated. Does anyone remember? I don't know about the Ada 9X discussions specifically, but if you think about it, there are a lot of obvious problems with trying to redefine ":=". The biggest problem is that it is not a subprogram - it is a primitive feature of the language. I believe this might be an example of Godel's Theorem. There are some features of the language (any language) that cannot be expressed in the language itself. As a "function" it would require that a) the left parameter be treated as "out" and b) that the function need not return a result. (or that it could be ignored. Does a statement like: "X < Y ;" make sense in Ada?) As a procedure, you'd have to allow procedures to have symbol names - which opens up a whole can of worms. Further, it would mean allowing "infix procedures" which is hard to make sense of - or at least could make programs look really strange. I'm sure there are dozens of other reasons why it was decided not to provide a means of letting the user define assignment. I'd think it would require perverting, warping and twisting language concepts too much. (Look at the semantics of C++ construction/destruction sometime - especially as it applies to function parameters - and see what an abomination that can become! :-) -- ====================================================================== Marin David Condic - Quadrus Corporation - http://www.quadruscorp.com/ Send Replies To: m c o n d i c @ q u a d r u s c o r p . c o m Visit my web site at: http://www.mcondic.com/ "Giving money and power to Government is like giving whiskey and car keys to teenage boys." -- P. J. O'Rourke ====================================================================== ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Constructors/Destructors in Ada95 2000-10-25 0:00 ` Marin David Condic @ 2000-10-25 0:00 ` dmitry6243 2000-10-25 0:00 ` mark.biggar 2000-10-25 0:00 ` Pascal Obry 2000-10-27 7:12 ` Ray Blaak 1 sibling, 2 replies; 35+ messages in thread From: dmitry6243 @ 2000-10-25 0:00 UTC (permalink / raw) In article <39F6D201.73C006FA@acm.org>, Marin David Condic <mcondic.nospam@acm.org> wrote: > Ray Blaak wrote: > > > I really would like to be able to do: > > > > procedure ":="(target : in out T; source : in T); > > > > so as to have complete control over what is happening. I vaguely recall some > > rationale from the Ada 9X discussions for why user-defined assignment per se > > was not incorporated. Does anyone remember? > > Does a > statement like: "X < Y ;" make sense in Ada?) As a procedure, you'd have to allow > procedures to have symbol names - which opens up a whole can of worms. Further, it > would mean allowing "infix procedures" which is hard to make sense of - or at least > could make programs look really strange. It would be nice (it is in my private Ada to-do list for a long time): function "*" (Left, Right : Matrix) return Matrix; -- Produces a new object procedure "*" (Left : in out Matrix; Right : Matrix); -- Multiplies Left to Right "in-place" So I would count it as an advantage. There is another. If you have procedure ":="(target : in out T; source : in T); then your assignment may take a look on the left-side object before its destruction. Ada's Adjust is much more (IMO too much) specialized. > I'm sure there are dozens of other reasons why it was decided not to provide a > means of letting the user define assignment. I'd think it would require perverting, > warping and twisting language concepts too much. I think that the major reason was the decision to limit user defined assigments by Controlled types. Doing so you must drop ":=" form, which ontherwise would permanently remind you that actually all types might be assigned (:-)) > (Look at the semantics of C++ > construction/destruction sometime - especially as it applies to function parameters > - and see what an abomination that can become! :-) So let's show them how to do it right (:-)) -- Regards, Dmitry Kazakov Sent via Deja.com http://www.deja.com/ Before you buy. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Constructors/Destructors in Ada95 2000-10-25 0:00 ` dmitry6243 @ 2000-10-25 0:00 ` mark.biggar 2000-10-26 11:44 ` dmitry6243 2000-10-26 21:31 ` Tucker Taft 2000-10-25 0:00 ` Pascal Obry 1 sibling, 2 replies; 35+ messages in thread From: mark.biggar @ 2000-10-25 0:00 UTC (permalink / raw) In article <8t6pi9$9s8$1@nnrp1.deja.com>, dmitry6243@my-deja.com wrote: > In article <39F6D201.73C006FA@acm.org>, > Marin David Condic <mcondic.nospam@acm.org> wrote: > > Ray Blaak wrote: > > > > > I really would like to be able to do: > > > > > > procedure ":="(target : in out T; source : in T); > > > > > > so as to have complete control over what is happening. I vaguely recall some > > > rationale from the Ada 9X discussions for why user-defined assignment per se > > > was not incorporated. Does anyone remember? > > > > Does a > > statement like: "X < Y ;" make sense in Ada?) As a procedure, you'd have to allow > > procedures to have symbol names - which opens up a whole can of worms. Further, it > > would mean allowing "infix procedures" which is hard to make sense of - or at least > > could make programs look really strange. > > It would be nice (it is in my private Ada to-do list for a long time): > > function "*" (Left, Right : Matrix) return Matrix; -- Produces a new object > procedure "*" (Left : in out Matrix; Right : Matrix); -- Multiplies Left to > Right "in-place" > > So I would count it as an advantage. There is another. If you have > > procedure ":="(target : in out T; source : in T); > > then your assignment may take a look on the left-side object before its > destruction. Ada's Adjust is much more (IMO too much) specialized. > > > I'm sure there are dozens of other reasons why it was decided not to provide a > > means of letting the user define assignment. I'd think it would require perverting, > > warping and twisting language concepts too much. > > I think that the major reason was the decision to limit user defined > assigments by Controlled types. Doing so you must drop ":=" form, which > ontherwise would permanently remind you that actually all types might be > assigned (:-)) One of the problems with this proposal (redefineing ":=") is that you would have to define Initialize, Adjust and Finialize anyway as you need them to implement value parameter passing, temporary creation and function return values correctly. Each of those is like assingment, but not exactly the same being, built out of the three primitives in different ways. So it makes more sense to just define the three primitives and have the compiler generate standard usage sequences then to redefine ":=" and have strange and hard to understand things happen. There's a reason that C++ has several types of constructors and in many ways the Ada mechanism is simpler. -- Mark Biggar mark.biggar@trustedsyslabs.com Sent via Deja.com http://www.deja.com/ Before you buy. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Constructors/Destructors in Ada95 2000-10-25 0:00 ` mark.biggar @ 2000-10-26 11:44 ` dmitry6243 2000-10-26 13:25 ` Robert A Duff 2000-10-26 17:55 ` tmoran 2000-10-26 21:31 ` Tucker Taft 1 sibling, 2 replies; 35+ messages in thread From: dmitry6243 @ 2000-10-26 11:44 UTC (permalink / raw) In article <8t6vhc$fmb$1@nnrp1.deja.com>, mark.biggar@trustedsyslabs.com wrote: > In article <8t6pi9$9s8$1@nnrp1.deja.com>, > dmitry6243@my-deja.com wrote: > > In article <39F6D201.73C006FA@acm.org>, > > Marin David Condic <mcondic.nospam@acm.org> wrote: > > > Ray Blaak wrote: > > > > > > > I really would like to be able to do: > > > > > > > > procedure ":="(target : in out T; source : in T); > > > > > > > > so as to have complete control over what is happening. I vaguely > recall some > > > > rationale from the Ada 9X discussions for why user-defined > assignment per se > > > > was not incorporated. Does anyone remember? > > > > > > Does a > > > statement like: "X < Y ;" make sense in Ada?) As a procedure, you'd > have to allow > > > procedures to have symbol names - which opens up a whole can of > worms. Further, it > > > would mean allowing "infix procedures" which is hard to make sense > of - or at least > > > could make programs look really strange. > > > > It would be nice (it is in my private Ada to-do list for a long time): > > > > function "*" (Left, Right : Matrix) return Matrix; -- Produces a new > object > > procedure "*" (Left : in out Matrix; Right : Matrix); -- Multiplies > Left to > > Right "in-place" > > > > So I would count it as an advantage. There is another. If you have > > > > procedure ":="(target : in out T; source : in T); > > > > then your assignment may take a look on the left-side object before > its > > destruction. Ada's Adjust is much more (IMO too much) specialized. > > > > > I'm sure there are dozens of other reasons why it was decided not to > provide a > > > means of letting the user define assignment. I'd think it would > require perverting, > > > warping and twisting language concepts too much. > > > > I think that the major reason was the decision to limit user defined > > assigments by Controlled types. Doing so you must drop ":=" form, > which > > ontherwise would permanently remind you that actually all types might > be > > assigned (:-)) > > One of the problems with this proposal (redefineing ":=") is that > you would have to define Initialize, Adjust and Finialize anyway > as you need them to implement value parameter passing, temporary > creation and function return values correctly. Each of those is > like assingment, but not exactly the same being, built out of the > three primitives in different ways. Yes. However, actually it is 5 primitives: Allocator (System.Storage_Pools), Default constructor (Initialize), Copy constructor ("memmove" + Adjust), Destructor (Finalize), Deallocator (System.Storage_Pools) > So it makes more sense to just > define the three primitives and have the compiler generate > standard usage sequences then to redefine ":=" and have strange > and hard to understand things happen. Most of programs are making strange and and hard to understand things (:-)). Yes. The compiler would generate the default assigment out of the primitives and the programmer would override it if he were not satisfied with the result. There are lot of pitfalls here, but Initialize-Adjust-Finalize is neither free of them. I had got a very nasty bug when a controlled type was passed by copy instead of by reference as I thought (or better to say, didn't care). > There's a reason that C++ has several types of constructors and in > many ways the Ada mechanism is simpler. One needs at least two constructors, one for initialization, another for creating temporal values (for instance, when an object is passed by copy). We have this in Ada, we have this in C++. I see nothing wrong if Ada would offer an ability to have initializing constructors with parameters too. When X : String (80); is legal, why: X : MyType (Y, Z, 3.1415); cannot be allowed in addition to famous: X : MyType := +(Y, Z, 3.1415); -- (:-)) User defined aggregates could also be a nice feature. -- Regards, Dmitry Kazakov Sent via Deja.com http://www.deja.com/ Before you buy. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Constructors/Destructors in Ada95 2000-10-26 11:44 ` dmitry6243 @ 2000-10-26 13:25 ` Robert A Duff 2000-10-27 8:10 ` dmitry6243 2000-10-26 17:55 ` tmoran 1 sibling, 1 reply; 35+ messages in thread From: Robert A Duff @ 2000-10-26 13:25 UTC (permalink / raw) dmitry6243@my-deja.com writes: > There are lot of pitfalls here, but Initialize-Adjust-Finalize is > neither free of them. I had got a very nasty bug when a controlled type > was passed by copy instead of by reference as I thought (or better to > say, didn't care). Controlled types are always passed by reference. - Bob ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Constructors/Destructors in Ada95 2000-10-26 13:25 ` Robert A Duff @ 2000-10-27 8:10 ` dmitry6243 0 siblings, 0 replies; 35+ messages in thread From: dmitry6243 @ 2000-10-27 8:10 UTC (permalink / raw) In article <wccwvevbuph.fsf@world.std.com>, Robert A Duff <bobduff@world.std.com> wrote: > dmitry6243@my-deja.com writes: > > > There are lot of pitfalls here, but Initialize-Adjust-Finalize is > > neither free of them. I had got a very nasty bug when a controlled type > > was passed by copy instead of by reference as I thought (or better to > > say, didn't care). > > Controlled types are always passed by reference. Sorry. I should be more precise. Actually a non-controlled record was passed by copy. I don't remember all details now. It was an attempt to implement sets, so that assingment would copy reference and increment use-count. It was really tricky. -- Regards, Dmitry Kazakov Sent via Deja.com http://www.deja.com/ Before you buy. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Constructors/Destructors in Ada95 2000-10-26 11:44 ` dmitry6243 2000-10-26 13:25 ` Robert A Duff @ 2000-10-26 17:55 ` tmoran 2000-10-27 8:10 ` dmitry6243 1 sibling, 1 reply; 35+ messages in thread From: tmoran @ 2000-10-26 17:55 UTC (permalink / raw) >X : String (80); >X : MyType (Y, Z, 3.1415); You can't do X : String (3.1415); but you can do X : MyType (Y, Z, 3); ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Constructors/Destructors in Ada95 2000-10-26 17:55 ` tmoran @ 2000-10-27 8:10 ` dmitry6243 0 siblings, 0 replies; 35+ messages in thread From: dmitry6243 @ 2000-10-27 8:10 UTC (permalink / raw) In article <Je_J5.358392$i5.5719531@news1.frmt1.sfba.home.com>, tmoran@bix.com wrote: > >X : String (80); > >X : MyType (Y, Z, 3.1415); > You can't do > X : String (3.1415); > but you can do > X : MyType (Y, Z, 3); > Using discriminants? What if MyType has no discriminants? -- Regards, Dmitry Kazakov Sent via Deja.com http://www.deja.com/ Before you buy. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Constructors/Destructors in Ada95 2000-10-25 0:00 ` mark.biggar 2000-10-26 11:44 ` dmitry6243 @ 2000-10-26 21:31 ` Tucker Taft 2000-10-27 8:46 ` dmitry6243 1 sibling, 1 reply; 35+ messages in thread From: Tucker Taft @ 2000-10-26 21:31 UTC (permalink / raw) mark.biggar@trustedsyslabs.com wrote: > ... > > One of the problems with this proposal (redefineing ":=") is that > you would have to define Initialize, Adjust and Finialize anyway > as you need them to implement value parameter passing, temporary > creation and function return values correctly. Each of those is > like assingment, but not exactly the same being, built out of the > three primitives in different ways. So it makes more sense to just > define the three primitives and have the compiler generate > standard usage sequences then to redefine ":=" and have strange > and hard to understand things happen. This is part of the reason we did not allow the user to directly define ":=". Another important reason has to do with assignment of composite objects (e.g. records and arrays) containing objects with user-defined assignment. One desirable feature is that the assignment for a record, for example, is defined in terms of the assignment of its individual components. Unfortunately, there are cases of record assignment in Ada where the left-hand-side doesn't contain a component that the right-hand-side does. This happens if the left-hand-side is an unconstrained record with discriminants, and the right-hand-side happens to have different values for the discriminants than the values of the left-hand-side. As a result of the assignment, some components of the left-hand-side may disappear, and some may come into existence. For example: type Rec(B : Boolean := False) is record X : Cool_Controlled_Type; case B is when True => Y : Fancy_Controlled_Type; when False => Z : Another_Controlled_Type; end case; end record; R1 : Rec; -- Defaults to B => False R2 : Rec(B => True); ... R1 := R2; -- R1.Z disappears, R1.Y is created, -- R1.X overwritten It would be tricky at best to define how or whether user-defined ":=" for Cool_, Fancy_, and Another_Controlled_Type should be used in the above case. However, with the user-defined operations broken down into Finalize and Adjust, it is relatively straightforward to specify what happens: R1.Z is finalized, R1.Y is adjusted after copying from R2.Y, and R1.X is first finalized, and then adjusted after copying from R2.X. One viable semantics would be to specify that user-defined assignment is used only for those cases where the component already exists, and is being overwritten, and finalize or adjust is used for the other cases. That could work, though it would prevent using block copy. With the current approach, block copy can be used to actually copy the "bits" from R2 to R1, so long as any appropriate finalizations are done before the copy, and any appropriate adjusts are done afterward. If the record has a bunch of non-controlled components, then being able to use block copy might be seen as an important advantage of the Ada 95 approach. Another nice feature of the current mechanism is that the compiler can create a single "whole record finalize" and another "whole record adjust" procedure, which are simply "roll ups" of the per-component finalize/adjust operations, possibly with an implicit "case" statement based on the current value of the discriminants. An assignment statement would then involve a call on the whole-record finalize, followed by a block copy, followed by a call on the whole-record adjust. (Also note that an explicit initialization in a declaration "looks like" an assignment statement, but it couldn't use the user-defined assignment, because the left-hand side isn't yet initialized. It really just needs a copy and adjust. No finalizes should be performed.) Creating an equivalent "whole-record-assign" rollup would certainly be possible, though the details of such a routine for a record type like "Rec" above would be pretty painful. You would compare the values of the discriminants of the left and right sides, and then depending on the various possibilities, one would do one of three things for each component: finalize LHS component, copy RHS into LHS and adjust, or user-defined-assign RHS into LHS. The order of doing this would be somewhat tricky, and there are sometimes "implicit" components that need copying as well. Finally, somebody has to do the constraint check when the left-hand side is *not* unconstrained, handle the case of self-assignment, handle the case of slice assignments (deciding between left-to-right or right-to-left based on relative start addresses) and there are issues of abort deferral, etc. Despite all the above "moaning and groaning," it still might be useful to allow user-defined assignment, even if it is only used in certain cases (e.g. LHS exists, and is initialized, and will still exist after the assignment). Presumably the user-defined assignment would take over the constraint check, and perhaps the check for self-assignment. I suppose it might be nice for the compiler to generate the check for self-assignment, since it is needed at most once for an assignment statement (it is not needed on each component), and it will often be possible to optimize it away. In most cases, the user-defined assignment would just be an optimization. However, because it would take over the constraint check, the user-defined assignment could also take on the job of implicit subtype conversion if desired. E.g., if you have a discriminated type like: type Text(Max : Natural) is record Data : String(1..Max); end record; a user-defined assignment routine could automatically pad or chop on assignment, rather than just complaining about mismatched discriminants. One final advantage of the Ada 95 approach has to do with maintenance. If the user provides the assignment operation, then presumably they have to individually assign each of the components. If a new component is added, there is no automatic handling of the new component, and it might be forgotten in the user-defined assignment operation. By contrast, with the finalize/adjust approach, the finalize for a record type doesn't need to call the finalize operation for each component -- that happens automatically. The user-defined finalize for a record type only needs to worry about finalizations over and above those required for the individual components. Ditto for adjust. I suppose for user-defined assignment, one could provide some way to get access to the underlying predefined assignment operation (which omits calls on finalize/adjust for the record type), so that one could use that to handle copying all the components, before or after some special work is done at the record level. E.g., one might save the value of some component of the LHS, then do the predefined assignment of the RHS into the LHS, and then do a deep copy of the new value of the component potentially reusing space allocated for the saved component value. This would presumably be more efficient than doing the finalize and adjust, which by necessity need to operate independently of one another. > > There's a reason that C++ has several types of constructors and in > many ways the Ada mechanism is simpler. Also, C++ doesn't have discriminants, at least not explicitly (users sometimes define structs with an array at the end that can be extended), so the problem of "composing" a struct assignment out of the assignment for the individual components is not as difficult for the compiler. > > -- > Mark Biggar > mark.biggar@trustedsyslabs.com -Tucker Taft -- -Tucker Taft stt@averstar.com http://www.averstar.com/~stt/ Technical Director, Commercial Division, AverStar (formerly Intermetrics) (http://www.averstar.com/services/IT_consulting.html) Burlington, MA USA ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Constructors/Destructors in Ada95 2000-10-26 21:31 ` Tucker Taft @ 2000-10-27 8:46 ` dmitry6243 0 siblings, 0 replies; 35+ messages in thread From: dmitry6243 @ 2000-10-27 8:46 UTC (permalink / raw) In article <39F8A2CB.CA319F5@averstar.com>, Tucker Taft <stt@averstar.com> wrote: > mark.biggar@trustedsyslabs.com wrote: > > ... > > > > One of the problems with this proposal (redefineing ":=") is that > > you would have to define Initialize, Adjust and Finialize anyway > > as you need them to implement value parameter passing, temporary > > creation and function return values correctly. Each of those is > > like assingment, but not exactly the same being, built out of the > > three primitives in different ways. So it makes more sense to just > > define the three primitives and have the compiler generate > > standard usage sequences then to redefine ":=" and have strange > > and hard to understand things happen. > > This is part of the reason we did not allow the user > to directly define ":=". Another important reason has to > do with assignment of composite objects (e.g. records > and arrays) containing objects with user-defined > assignment. One desirable feature is that the assignment > for a record, for example, is defined in terms of the > assignment of its individual components. Unfortunately, > there are cases of record assignment in Ada where > the left-hand-side doesn't contain a component that > the right-hand-side does. This happens if the left-hand-side > is an unconstrained record with discriminants, and the > right-hand-side happens to have different values for the > discriminants than the values of the left-hand-side. > As a result of the assignment, some components of the > left-hand-side may disappear, and some may come into existence. > > For example: > > type Rec(B : Boolean := False) is record > X : Cool_Controlled_Type; > case B is > when True => > Y : Fancy_Controlled_Type; > when False => > Z : Another_Controlled_Type; > end case; > end record; > > R1 : Rec; -- Defaults to B => False > R2 : Rec(B => True); > > ... > > R1 := R2; -- R1.Z disappears, R1.Y is created, > -- R1.X overwritten > > It would be tricky at best to define how or whether > user-defined ":=" for Cool_, Fancy_, and Another_Controlled_Type > should be used in the above case. [...] I think that an assumption that Adjust should be generated from user-defined ":=" is wrong, or at least very hard to implement. IMO, used-defined ":=" should have no special semantic. It is not an alternative to the copy constructor (= copy + Adjust). The single link between them is that the default ":=" is generated as Finalize, copy, Adjust. In the given example, the compiler should simply ignore ":=" defined for the types of Rec's components. Another question is, whether copy constructor should be splitted into block-copy and Adjust. -- Regards, Dmitry Kazakov Sent via Deja.com http://www.deja.com/ Before you buy. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Constructors/Destructors in Ada95 2000-10-25 0:00 ` dmitry6243 2000-10-25 0:00 ` mark.biggar @ 2000-10-25 0:00 ` Pascal Obry 2000-10-26 0:00 ` dmitry6243 1 sibling, 1 reply; 35+ messages in thread From: Pascal Obry @ 2000-10-25 0:00 UTC (permalink / raw) dmitry6243@my-deja.com writes: > In article <39F6D201.73C006FA@acm.org>, > > function "*" (Left, Right : Matrix) return Matrix; -- Produces a new object > procedure "*" (Left : in out Matrix; Right : Matrix); -- Multiplies Left to > Right "in-place" I'am not an expert in this field but I really fail to see how it is possible to multiply two matrix without creating a temporary one ! So I'am not sure your example is a good one :) Pascal. -- --|------------------------------------------------------ --| Pascal Obry Team-Ada Member --| 45, rue Gabriel Peri - 78114 Magny Les Hameaux FRANCE --|------------------------------------------------------ --| http://perso.wanadoo.fr/pascal.obry --| --| "The best way to travel is by means of imagination" ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Constructors/Destructors in Ada95 2000-10-25 0:00 ` Pascal Obry @ 2000-10-26 0:00 ` dmitry6243 0 siblings, 0 replies; 35+ messages in thread From: dmitry6243 @ 2000-10-26 0:00 UTC (permalink / raw) In article <uem14bvc6.fsf@wanadoo.fr>, Pascal Obry <p.obry@wanadoo.fr> wrote: > > dmitry6243@my-deja.com writes: > > > In article <39F6D201.73C006FA@acm.org>, > > > > function "*" (Left, Right : Matrix) return Matrix; -- Produces a new object > > procedure "*" (Left : in out Matrix; Right : Matrix); -- Multiplies Left to > > Right "in-place" > > I'am not an expert in this field but I really fail to see how it is possible > to multiply two matrix without creating a temporary one ! So I'am not sure > your example is a good one :) It was about 15 years I wrote my last program for linear algebra. That time memory was a treasure (:-)). So I am not an expert too. In case of matrices one needs only one row/column of scratch memory, which is of course better than an allocation of the complete matrix. And there are lots of special matrices used much oftener than general dense matrices. --- Regards, Dmitry Kazakov Sent via Deja.com http://www.deja.com/ Before you buy. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Constructors/Destructors in Ada95 2000-10-25 0:00 ` Marin David Condic 2000-10-25 0:00 ` dmitry6243 @ 2000-10-27 7:12 ` Ray Blaak 1 sibling, 0 replies; 35+ messages in thread From: Ray Blaak @ 2000-10-27 7:12 UTC (permalink / raw) Marin David Condic <mcondic.nospam@acm.org> writes: > Ray Blaak wrote: > > I really would like to be able to do: > > > > procedure ":="(target : in out T; source : in T); > there are a lot of obvious problems with trying to redefine > ":=". The biggest problem is that it is not a subprogram - it is a primitive > feature of the language. I believe this might be an example of Godel's > Theorem. There are some features of the language (any language) that cannot > be expressed in the language itself. As a "function" it would require that a) > the left parameter be treated as "out" and b) that the function need not > return a result. (or that it could be ignored. Does a statement like: "X < Y > ;" make sense in Ada?) As a procedure, you'd have to allow procedures to have > symbol names - which opens up a whole can of worms. Further, it would mean > allowing "infix procedures" which is hard to make sense of - or at least > could make programs look really strange. I don't think syntax issues would be a major problem here. It can't be a function, since a return value makes no sense -- we need to operate on the target directly. So yes, we would introduce procedures to have (the single possible) "operator" name. It is not really a Godel limitation. The problem is that Ada is missing the necessary expressive power, likely on purpose in this case. The existence of user-defined assignment in C++ indicates that it is quite doable in theory, though, so it is only a matter of deciding how to extend Ada, if at all. But this is a minor change as far as the Ada grammar goes. As for wierd infix procedures, it would look quite normal: a := b; The wierd thing would be to see: ":="(a, b); But that is not complicated from a parsing point of view. Still, parsing problems can be avoided by having a type's assigner be accessible from T'Assign, and then allowing: procedure DeepCopy(target : in out T; source : in T); for T'Assign use DeepCopy; One problem I can think of is that we need to access the primitive assignment in order to implement the user-defined assignment. How does one refer to it? There is no "super" keyword in Ada. I suppose various renaming tricks are possible, but since they would always have to be done, that would quickly prove tedious. Perhaps we could have T'PrimitiveAssign be available for this purpose. However, I am looking for the subtle stuff. So far I have heard: a) discriminants problems involving the creation of fields when a different discriminat is specified - This one I would like to understand better. Why wouldn't something like this work: -- For all types T, T'Assign is the primitive ":=" operation. procedure ":="(target : in out T; source : in T) is begin -- do the usual thing: T'Assign(target, source); -- now the extra work for doing deep copy, etc. end ":="; b) User-defined assignment is not enough, also consider initialization and parameter passing. - Maybe so. So let's generalize these too. > I'm sure there are dozens of other reasons why it was decided not to provide > a means of letting the user define assignment. I'd think it would require > perverting, warping and twisting language concepts too much. (Look at the > semantics of C++ construction/destruction sometime - especially as it applies > to function parameters - and see what an abomination that can become! I don't have the sense that it warps things too much. C++ construction and user assignment seems quite understandable, at least for the usual cases. Are there any online archives somewhere that consider the issue? I think the Ada 9X discussions used to be, but they seem to have disappeared. -- Cheers, The Rhythm is around me, The Rhythm has control. Ray Blaak The Rhythm is inside me, blaak@infomatch.com The Rhythm has my soul. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Constructors/Destructors in Ada95 2000-10-24 0:00 ` Ray Blaak 2000-10-25 0:00 ` Francois Godme 2000-10-25 0:00 ` Marin David Condic @ 2000-10-27 18:11 ` Francois Godme 2000-10-30 11:36 ` Robert A Duff 2 siblings, 1 reply; 35+ messages in thread From: Francois Godme @ 2000-10-27 18:11 UTC (permalink / raw) Ray Blaak a �crit : > Francois Godme <fgodme@bigfoot.com> writes: > > > I. Non-primitive procedures used as constructors of limited instances: As > > limited instances can't be initialized with record aggregates, it is possible > > to write code which forgets to initialize all record fields. > > Forgetting to initialize a field is equivalent to using a default constructor, > no? In that case the Initialize routine can cover it. > Recall that the context was that defaulted record fields and the Initialize routine were said inadequate to initialize all instances. Take for example, the class Person. There are no such things as a default birth date, a default sex or a default eyes color for instances of the class Person. To provide methods to later fix the birth date, the sex and the eyes color to appropriate values opens up instances to mistakes. These three instance attributes should be constant and hence initialized by the constructor. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Constructors/Destructors in Ada95 2000-10-27 18:11 ` Francois Godme @ 2000-10-30 11:36 ` Robert A Duff 2000-10-30 22:03 ` dale 0 siblings, 1 reply; 35+ messages in thread From: Robert A Duff @ 2000-10-30 11:36 UTC (permalink / raw) Francois Godme <fgodme@bigfoot.com> writes: > Take for example, the class Person. There are no such things as a > default birth date, a default sex or a default eyes color for > instances of the class Person. To provide methods to later fix the > birth date, the sex and the eyes color to appropriate values opens up > instances to mistakes. These three instance attributes should be > constant and hence initialized by the constructor. You can use "(<>)" as the discriminant part to prevent default initialization. Then initialize the thing with a function call. (But as you or somebody pointed out, this unfortunately does not work for limited types.) - Bob ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Constructors/Destructors in Ada95 2000-10-30 11:36 ` Robert A Duff @ 2000-10-30 22:03 ` dale 0 siblings, 0 replies; 35+ messages in thread From: dale @ 2000-10-30 22:03 UTC (permalink / raw) Robert A Duff wrote: > You can use "(<>)" as the discriminant part to prevent default > initialization. Then initialize the thing with a function call. > (But as you or somebody pointed out, this unfortunately does not > work for limited types.) I think it also looks very ugly, and is certainly non intuitive. For a language that is based on the maxim of "maximum readability" i think it fails badly here. Dale ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Constructors/Destructors in Ada95 2000-10-19 0:00 ` Francois Godme 2000-10-19 0:00 ` Ted Dennison 2000-10-20 0:00 ` Tucker Taft @ 2000-10-22 0:00 ` rwilson007007 2000-10-22 0:00 ` Francois Godme 2 siblings, 1 reply; 35+ messages in thread From: rwilson007007 @ 2000-10-22 0:00 UTC (permalink / raw) in order to achieve the same effect as constructor arguments in c++ it is helpful to define an attributes class for each application-object class (with the same inheritance pattern as the application classes). the attributes class tagged record contains a field for each application -class tagged record field requiring explicit initialization. then, define the base class tagged record for your application-object classes with a classwide access value to a constant attributes class instance as one of its members. finally, the base class constructor reads the initial-attributes values for its attributes member from config files (for example). the inheriting classes then look-up the appropriate initial values in This.Attributes (for "Initialize (This : in out access Object)").... another way is to is enclose your classes in generic packages with the generic formal parameters corresponding to constructor arguments. however, this would seem to force a singleton pattern. --rwilson Sent via Deja.com http://www.deja.com/ Before you buy. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Constructors/Destructors in Ada95 2000-10-22 0:00 ` rwilson007007 @ 2000-10-22 0:00 ` Francois Godme 2000-10-24 0:00 ` rwilson007007 0 siblings, 1 reply; 35+ messages in thread From: Francois Godme @ 2000-10-22 0:00 UTC (permalink / raw) rwilson007007@my-deja.com a �crit : > in order to achieve the same effect as constructor arguments in c++ it > is helpful to define an attributes class for each application-object > class (with the same inheritance pattern as the application classes). > the attributes class tagged record contains a field for each application > -class tagged record field requiring explicit initialization. > > then, define the base class tagged record for your > application-object classes with a classwide access value to a > constant attributes class instance as one of its members. > > finally, the base class constructor reads the initial-attributes values > for its attributes member from config files (for example). the > inheriting classes then look-up the appropriate initial values in > This.Attributes (for "Initialize (This : in out access Object)").... > > another way is to is enclose your classes in generic packages with the > generic formal parameters corresponding to constructor arguments. > however, this would seem to force a singleton pattern. To rwilson, I will say that I am not sure that I fully undestand its proposal. For instance, I am not sure how different instances get initialized with different values in these scheme. Also, I am not sure if it needs not twice the memory, once in the application classes and once in the initializing classes. Anyway, I admit that for exemple with a public access discriminant to a string in the base class, the Initialize procedures could lookup somewhere, somehow with this name for values to initialize the instance. I find it too difficult to handle and prefer Tucker Taft's direct manner with non-primitive functions returning initialized instances for non-limited types and non-primitive procedures for limited types. Marin David Condic has said: "Remember that Ada is not C++. You can pretty much get the same net effect of constructors and destructors in Ada - but not in exactly the same way. So you change the model instead. Since Ada doesn't treat assignment the same way as C++ and you don't have the same parameter features, you've got to work with what Ada does provide and try not to make it look exactly like C++. The job does get done and, IMHO, it is a lot less semantically messy when done in Ada as opposed to C++." To Marin David Condic, I will say, well, recently, the model has been changed to make it look more like C++ by adding the "with type" feature which was felt lacking after feature comparisons with Java and C++. Some people complained they couldn't get the work done with what Ada provides. I take C++ as an exemple because C++ got inspired a lot by Ada83 in my opinion. C++ has pragmas, inlined routines, generics (templates), public and private parts (as well as protected parts), parameter passing modes, default parameters, constant objects, operators and methods overloading, (poor) enumeration types, exceptions, renamings (you can think of C++ references as renamings of objects.). C++ has also well-thought constructors. No pun intended. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Constructors/Destructors in Ada95 2000-10-22 0:00 ` Francois Godme @ 2000-10-24 0:00 ` rwilson007007 0 siblings, 0 replies; 35+ messages in thread From: rwilson007007 @ 2000-10-24 0:00 UTC (permalink / raw) F. Godme: > proposal. For instance, I am not sure how different instances get > initialized with different values in these scheme. Also, I am not sure the scheme i had in mind is sometimes known as a "factory pattern" - have a generic create & destroy procedures which take a string name, look for that name in a file, retrieve attributes associated with that name in the file, and then invoke ada.finalization for the base class, setting its attributes pointer for use in subsequent subclass initialize invocations. roughly, it goes like: --# package Object_Life_Cycle is generic type Object is tagged abstract private; package Factory is type Ref is access all Object'Class; -- Create will invoke "This := new Object" (triggering -- Ada.Finalization.Initialize) in its body -- (note - 'Name' is used to lookup attributes from a file) function Create (Name : in String) return Ref; function Destroy (This : in out Ref); end Factory; end Object_Life_Cycle; --# -- in another ada module --# package Attributes_Base_Class is type Object is abstract tagged with record Name : constant String; record; end Base; type Ref is access all Object'Class; end Attributes_Base_Class; --# -- et in another ada module... --# with Attributes_Base_Class; with Ada.Finalization; package Base_Class is type Object is new Ada.Finalization.Controlled with record Attributes : Attributes_Base_Class.Ref; end Object; type Ref is access all Object'Class; private procedure Initialize (This : in out Object); procedure Finalize (This : in out Object); end Base_Class; --# --et in another ada module --# with Attributes_Base_Class; with Base_Class; with Object_Life_Cycle; package My_Class is type Colors is (Red, Yellow, Green, Blue, White, Black); type Attributes is new Attributes_Base_Class.Object with record Height : Integer; Width : Integer; Length : Integer; Depth : Integer; Mass : Integer; Color : Colors; Age : Duration; end record; type Object is private; type Ref is access all Object'Class; -- method declarations go here function Age (This : in Ref) return Integer; function Color (This : in Ref) return Colors; procedure Evolve (This : in Ref); package Factory is new Object_Life_Cycle.Factory (Object => Object); private type Object is new Base_Class.Object with record Actual_Age : Duration; Current_Color : Colors; Power : Integer; end record; procedure Initialize (This : in out Object); procedure Finalize (This : in out Object); end My_Class; --# -- et in ada_main --# with My_Class; procedure Ada_Main is My_Object : My_Class.Ref; Current_Age : Duration; Actual_Color : My_Class.Colors; begin My_Object := My_Class.Factory.Create (Name => "MY_FIRST_OBJECT"); My_Object_Life: loop -- forever My_Class.Evolve (This => My_Object); Current_Age := My_Class.Age (This => My_Object); Actual_Color := My_Class.Color (This => My_Object); Text_Io.Put_Line ("My" & My_Class.Colors'Image (Actual_Color) & " Object is" & Duration'Image (Current_Age) & " milliseconds old..."); if Current_Age > 25.0 then My_Class.Factory.Destory (This => My_Object); Text_Io.Put_Line ("My_Object is dead!"); exit My_Object_Life; end if; end loop My_Object_Life; end Ada_Main; --# -- et (finally) in a plain text file: # configuration parameters for named objects go here My_First_Object : My_Class.Attributes; My_First_Object.Height = 100 My_First_Object.Width = 200 My_First_Object.Length = 40 My_First_Object.Depth = -20 My_First_Object.Mass = 0 My_First_Object.Color = My_Class.Red My_First_Object.Age = 0.0 Sent via Deja.com http://www.deja.com/ Before you buy. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Constructors/Destructors in Ada95 2000-10-18 0:00 Francois Godme 2000-10-19 0:00 ` Marin David Condic 2000-10-19 0:00 ` tmoran @ 2000-10-19 0:00 ` Ted Dennison 2 siblings, 0 replies; 35+ messages in thread From: Ted Dennison @ 2000-10-19 0:00 UTC (permalink / raw) Francois Godme wrote: > Where can I find articles, papers, or posted messages explaining me the > reasons for the lack of support for Constructors/Destructors directly in > the language. I have heard that, in 1995, Tucker Taft on c.l.a posted > several messages on this very subject. The Ada95 Rationale would be a good place to look for all the "Why?" questions you might have. Its online at http://www.adaic.org/standards/95rat/RAThtml/rat95-contents.html -- T.E.D. Home - mailto:dennison@telepath.com Work - mailto:dennison@ssd.fsi.com WWW - http://www.telepath.com/dennison/Ted/TED.html ICQ - 10545591 ^ permalink raw reply [flat|nested] 35+ messages in thread
end of thread, other threads:[~2000-10-30 22:03 UTC | newest] Thread overview: 35+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2000-10-29 22:51 Constructors/Destructors in Ada95 rwilson007007 2000-10-30 4:03 ` Ray Blaak 2000-10-30 12:13 ` Marin David Condic 2000-10-30 16:39 ` Randy Brukardt -- strict thread matches above, loose matches on Subject: below -- 2000-10-18 0:00 Francois Godme 2000-10-19 0:00 ` Marin David Condic 2000-10-19 0:00 ` tmoran 2000-10-19 0:00 ` Francois Godme 2000-10-19 0:00 ` Ted Dennison 2000-10-20 0:00 ` Tucker Taft 2000-10-20 0:00 ` Francois Godme 2000-10-21 0:00 ` Marin David Condic 2000-10-23 0:00 ` Francois Godme 2000-10-24 0:00 ` Ray Blaak 2000-10-25 0:00 ` Francois Godme 2000-10-25 0:00 ` Marin David Condic 2000-10-25 0:00 ` dmitry6243 2000-10-25 0:00 ` mark.biggar 2000-10-26 11:44 ` dmitry6243 2000-10-26 13:25 ` Robert A Duff 2000-10-27 8:10 ` dmitry6243 2000-10-26 17:55 ` tmoran 2000-10-27 8:10 ` dmitry6243 2000-10-26 21:31 ` Tucker Taft 2000-10-27 8:46 ` dmitry6243 2000-10-25 0:00 ` Pascal Obry 2000-10-26 0:00 ` dmitry6243 2000-10-27 7:12 ` Ray Blaak 2000-10-27 18:11 ` Francois Godme 2000-10-30 11:36 ` Robert A Duff 2000-10-30 22:03 ` dale 2000-10-22 0:00 ` rwilson007007 2000-10-22 0:00 ` Francois Godme 2000-10-24 0:00 ` rwilson007007 2000-10-19 0:00 ` Ted Dennison
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox