* How to test object hierarchy @ 2003-12-18 18:24 Pierre Favier 2003-12-19 0:15 ` Stephen Leake ` (2 more replies) 0 siblings, 3 replies; 19+ messages in thread From: Pierre Favier @ 2003-12-18 18:24 UTC (permalink / raw) I am wondering how to test for two objects which types both derive from a common root type if one of them derives from the other. In short, I am trying to run something like the following code which does not compile because the Class attribute applies to types or subtypes but not to objects: procedure Test_Hierarchy (Obj1 : in Root_Object'Class; Obj2 : in Root_Object'Class) is begin if Obj1 in Obj2'Class then -- Do something else -- Do something else end if; end Test_Hierarchy; Any suggestions on how to achieve the intended effect? ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: How to test object hierarchy 2003-12-18 18:24 How to test object hierarchy Pierre Favier @ 2003-12-19 0:15 ` Stephen Leake 2003-12-19 7:45 ` Pierre Favier 2003-12-19 10:53 ` Dmitry A. Kazakov 2003-12-19 17:24 ` Nick Roberts 2 siblings, 1 reply; 19+ messages in thread From: Stephen Leake @ 2003-12-19 0:15 UTC (permalink / raw) To: comp.lang.ada favierp@sofreavia.fr (Pierre Favier) writes: > I am wondering how to test for two objects which types both derive from a > common root type if one of them derives from the other. Interesting. Here's one way: with Ada.Strings.Unbounded; package Objects is type Root_Object is abstract tagged record Name : Ada.Strings.Unbounded.Unbounded_String; end record; type Object_1 is new Root_Object with record I : Integer; end record; type Object_1_1 is new Object_1 with record J : Integer; end record; end Objects; with Objects; with Ada.Text_Io; use Ada.Text_Io; with Ada.Tags; with Ada.Strings.Fixed; with Ada.Strings.Unbounded; procedure Test_Hierarchy is function "+" (Item : in String) return Ada.Strings.Unbounded.Unbounded_String renames Ada.Strings.Unbounded.To_Unbounded_String; function "+" (Item : in Ada.Strings.Unbounded.Unbounded_String) return String renames Ada.Strings.Unbounded.To_String; procedure Test (Obj1 : in Objects.Root_Object'Class; Obj2 : in Objects.Root_Object'Class) is Obj1_Type_Name : constant String := Ada.Tags.Expanded_Name (Obj1'Tag); Obj2_Type_Name : constant String := Ada.Tags.Expanded_Name (Obj2'Tag); begin if 0 /= Ada.Strings.Fixed.Index (Source => Obj1_Type_Name, Pattern => Obj2_Type_Name) then Put_Line (+Obj1.Name & " is in " & (+Obj2.Name)); else Put_Line (+Obj1.Name & " is not in " & (+Obj2.Name)); end if; end Test; Obj1 : Objects.Object_1 := (+"higher", 1); Obj2 : Objects.Object_1_1 := (+"lower", 2, 3); begin Test (Obj1, Obj2); Test (Obj2, Obj1); end Test_Hierarchy; make -r test_hierarchy.run gnatmake -k -O3 -gnatn -gnatwa -I.. test_hierarchy -largs -bargs -cargs gcc -c -I./ -O3 -gnatn -gnatwa -I.. -I- ..\test_hierarchy.adb gnatbind -aO./ -I.. -I- -x test_hierarchy.ali gnatlink test_hierarchy.ali ./test_hierarchy.exe higher is not in lower lower is in higher It does seem like you aught to be able to do this without string operations. -- -- Stephe ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: How to test object hierarchy 2003-12-19 0:15 ` Stephen Leake @ 2003-12-19 7:45 ` Pierre Favier 0 siblings, 0 replies; 19+ messages in thread From: Pierre Favier @ 2003-12-19 7:45 UTC (permalink / raw) Stephen Leake <stephen_leake@acm.org> wrote in message news:<mailman.138.1071792945.31149.comp.lang.ada@ada-france.org>... > favierp@sofreavia.fr (Pierre Favier) writes: > > > I am wondering how to test for two objects which types both derive from a > > common root type if one of them derives from the other. > > Interesting. Here's one way: > > ...... > > It does seem like you aught to be able to do this without string operations. Yes. I had thought of using tag's Expanded_Name like you suggested but was wondering whether there was a language feature that I was overlooking. If you look at spec of package Ada.Tags in GNAT you see the following function in the private part of the spec: function CW_Membership (Obj_Tag : Tag; Typ_Tag : Tag) return Boolean; -- Given the tag of an object and the tag associated to a type, return -- true if Obj is in Typ'Class. which could be used as is for two object tags instead of an object tag and a type tag. Why not make it public? Is any addition of this sort planned for Ada 200X? ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: How to test object hierarchy 2003-12-18 18:24 How to test object hierarchy Pierre Favier 2003-12-19 0:15 ` Stephen Leake @ 2003-12-19 10:53 ` Dmitry A. Kazakov 2003-12-19 14:35 ` Hyman Rosen 2003-12-19 17:25 ` Georg Bauhaus 2003-12-19 17:24 ` Nick Roberts 2 siblings, 2 replies; 19+ messages in thread From: Dmitry A. Kazakov @ 2003-12-19 10:53 UTC (permalink / raw) Pierre Favier wrote: > I am wondering how to test for two objects which types both derive from a > common root type if one of them derives from the other. In short, I am > trying to run something like the following code which does not compile > because the Class attribute applies to types or subtypes but not to > objects: > > procedure Test_Hierarchy (Obj1 : in Root_Object'Class; > Obj2 : in Root_Object'Class) is > begin > > if Obj1 in Obj2'Class then > > -- Do something > > else > > -- Do something else > > end if; > > end Test_Hierarchy; > > Any suggestions on how to achieve the intended effect? Unfortunately tags have no "<" defined. Otherwise, one could simply write Obj1'Tag < Obj2'Tag (in the sense Obj1 <: Obj2). However there is a trick to achieve what you want using dispatching. The idea is to emulate multiple dispatch and so you go as follows: procedure Do_It -- Obj1 :>= Obj2 ( Obj1 : in Root_Object'Class; Obj2 : in Root_Object'Class ); procedure Test_Hierarchy ( Obj1 : in Root_Object; -- Dispatches in this argument Obj2 : in Root_Object'Class; Recursion : Boolean := False ) is begin if Recursion or else Obj2 not in Root_Object'Class then Do_It (Obj1, Obj2); -- Deal with Obj1 :>= Obj2 else Test_Hierarchy (Obj2, Obj1, True); -- Dispatch again end if; end Test_Hierarchy; type Derived_Object is new Root_Object with ...; procedure Test_Hierarchy ( Obj1 : in Derived_Object; Obj2 : in Root_Object'Class; Recursion : Boolean := False ) is begin if Recursion or else Obj2 not in Derived_Object'Class or else Obj2 in Derived_Object then Do_It (Obj1, Obj2); -- Deal with Obj1 :>= Obj2 else Test_Hierarchy (Obj2, Obj1, True); -- Dispatch again end if; end Test_Hierarchy; You have to override Test_Hierarchy for each new type, but I suppose that "do something" in your code is dispatching anyway. When Test_Hierarchy is not commutative it gets a bit more complicated, but I think you have got the idea. -- Regards, Dmitry A. Kazakov www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: How to test object hierarchy 2003-12-19 10:53 ` Dmitry A. Kazakov @ 2003-12-19 14:35 ` Hyman Rosen 2003-12-19 17:07 ` Dmitry A. Kazakov 2003-12-19 23:26 ` Robert A Duff 2003-12-19 17:25 ` Georg Bauhaus 1 sibling, 2 replies; 19+ messages in thread From: Hyman Rosen @ 2003-12-19 14:35 UTC (permalink / raw) Dmitry A. Kazakov wrote: > You have to override Test_Hierarchy for each new type Which brings a question to my non Ada-knowing mind. I know that for a subprogram to be dispatching, it must be defined in the same package (or immediately after?) as the tagged type upon which it dispatches. Can an instantiation of a generic be dispatching in this way? Could I do (pardon the syntax errors) procedure Test_Hierarchy is new Generic_Test_Hierarchy(Type1=>Derived_Object); rather than copy the code each time? ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: How to test object hierarchy 2003-12-19 14:35 ` Hyman Rosen @ 2003-12-19 17:07 ` Dmitry A. Kazakov 2003-12-19 23:26 ` Robert A Duff 1 sibling, 0 replies; 19+ messages in thread From: Dmitry A. Kazakov @ 2003-12-19 17:07 UTC (permalink / raw) Hyman Rosen wrote: > Dmitry A. Kazakov wrote: >> You have to override Test_Hierarchy for each new type > > Which brings a question to my non Ada-knowing mind. > I know that for a subprogram to be dispatching, it > must be defined in the same package (or immediately > after?) as the tagged type upon which it dispatches. Before the freezing point, which is informally at the first "non-trivial" use of the type before the package specification end. > Can an instantiation of a generic be dispatching in > this way? Could I do (pardon the syntax errors) > procedure Test_Hierarchy is new > Generic_Test_Hierarchy(Type1=>Derived_Object); > rather than copy the code each time? Aside, it is actually what inheritance is for! The problem is that there is no [proper] multiple dispatch in Ada. Well, an implementation of a dispatching subprogram through instantiation of a generic one is not allowed in either Ada or C++. One step up. A generic primitive operation is also not allowed in both. Another step up. Generic types do exist in C++, but not in Ada, where same effect is achieved using generic packages. A strategic question is, whether one realy should exploit all possible combinations of inheritance [and all other language things] and generics. You know my opinion, down with generics! And there will be no question anymore! (:-)) -- Regards, Dmitry A. Kazakov www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: How to test object hierarchy 2003-12-19 14:35 ` Hyman Rosen 2003-12-19 17:07 ` Dmitry A. Kazakov @ 2003-12-19 23:26 ` Robert A Duff 2003-12-20 18:20 ` Robert I. Eachus 1 sibling, 1 reply; 19+ messages in thread From: Robert A Duff @ 2003-12-19 23:26 UTC (permalink / raw) Hyman Rosen <hyrosen@mail.com> writes: > Dmitry A. Kazakov wrote: > > You have to override Test_Hierarchy for each new type > > Which brings a question to my non Ada-knowing mind. > I know that for a subprogram to be dispatching, it > must be defined in the same package (or immediately > after?) as the tagged type upon which it dispatches. It must defined in the same package *spec* (visible part or private part). One obscure point is that if you override an inherited subprogram, it is dispatching. It has to be declared in the same declarative region in that case. > Can an instantiation of a generic be dispatching in > this way? Yes, it can be instance. It can also be a renaming. >... Could I do (pardon the syntax errors) > procedure Test_Hierarchy is new > Generic_Test_Hierarchy(Type1=>Derived_Object); > rather than copy the code each time? I didn't follow the entire discussion, but yes, I think that could work. - Bob ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: How to test object hierarchy 2003-12-19 23:26 ` Robert A Duff @ 2003-12-20 18:20 ` Robert I. Eachus 0 siblings, 0 replies; 19+ messages in thread From: Robert I. Eachus @ 2003-12-20 18:20 UTC (permalink / raw) Robert A Duff wrote: > Yes, it can be instance. It can also be a renaming. ... > I didn't follow the entire discussion, but yes, I think that could work. Before somebody gets bent all out of shape trying to implement the idea, there is a subtle gotcha here that has to be avoided. It is often difficult (but not impossible) to define the generic you want before the freezing point. There are two workarounds, which often occur naturally. The first is to make the signature of the subprogram dispatching. Then in the body, implement the subprogram as a generic instance. Or you can make the generic an operation of a parent type, so that the generic instantiation can appear before the freezing point of the child type, but after the freezing point of the parent. As I said, you may naturally not run into a problem. Depends on how you define the generic and other things. But if you do have a problem, move the instantiation to the body of the package that defines the type. -- Robert I. Eachus "The war on terror is a different kind of war, waged capture by capture, cell by cell, and victory by victory. Our security is assured by our perseverance and by our sure belief in the success of liberty." -- George W. Bush ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: How to test object hierarchy 2003-12-19 10:53 ` Dmitry A. Kazakov 2003-12-19 14:35 ` Hyman Rosen @ 2003-12-19 17:25 ` Georg Bauhaus 2003-12-20 11:13 ` Dmitry A. Kazakov 1 sibling, 1 reply; 19+ messages in thread From: Georg Bauhaus @ 2003-12-19 17:25 UTC (permalink / raw) Dmitry A. Kazakov <mailbox@dmitry-kazakov.de> wrote: : type Derived_Object is new Root_Object with ...; : procedure Test_Hierarchy : ( Obj1 : in Derived_Object; : Obj2 : in Root_Object'Class; : Recursion : Boolean := False : ) is : begin : if Recursion : or else Obj2 not in Derived_Object'Class : or else Obj2 in Derived_Object : then : Do_It (Obj1, Obj2); -- Deal with Obj1 :>= Obj2 : else : Test_Hierarchy (Obj2, Obj1, True); -- Dispatch again : end if; : end Test_Hierarchy; : : You have to override Test_Hierarchy for each new type, but I suppose that : "do something" in your code is dispatching anyway. When Test_Hierarchy is : not commutative it gets a bit more complicated, but I think you have got : the idea. Whenever I see an "if" testing for types I'm wondering whether these ifs should be turned "to the outside" into what they mean in the solution domain, but using language means. Is it really advantageous or necessary to have to do manual dispatching in your program? And I have the same question that Hyman has asked about generics, plus, should "with type" be mentioned in this context? -- Georg ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: How to test object hierarchy 2003-12-19 17:25 ` Georg Bauhaus @ 2003-12-20 11:13 ` Dmitry A. Kazakov 2003-12-21 4:34 ` Georg Bauhaus 0 siblings, 1 reply; 19+ messages in thread From: Dmitry A. Kazakov @ 2003-12-20 11:13 UTC (permalink / raw) Georg Bauhaus wrote: > Dmitry A. Kazakov <mailbox@dmitry-kazakov.de> wrote: > : type Derived_Object is new Root_Object with ...; > : procedure Test_Hierarchy > : ( Obj1 : in Derived_Object; > : Obj2 : in Root_Object'Class; > : Recursion : Boolean := False > : ) is > : begin > : if Recursion > : or else Obj2 not in Derived_Object'Class > : or else Obj2 in Derived_Object > : then > : Do_It (Obj1, Obj2); -- Deal with Obj1 :>= Obj2 > : else > : Test_Hierarchy (Obj2, Obj1, True); -- Dispatch again > : end if; > : end Test_Hierarchy; > : > : You have to override Test_Hierarchy for each new type, but I suppose > : that "do something" in your code is dispatching anyway. When > : Test_Hierarchy is not commutative it gets a bit more complicated, but I > : think you have got the idea. > > Whenever I see an "if" testing for types I'm wondering whether > these ifs should be turned "to the outside" into what they mean > in the solution domain, but using language means. Is it really > advantageous or necessary to have to do manual dispatching in > your program? R-r-right. The rest is easy, just to write an AI for multiple dispatch in Ada! (:-)) Ideally, the language should allow to program without any explicit testing/casting for types. I remember a fierce discussion in comp.object on this topic. The result, as always, was unsettled. Then not always types do reflect the solution domain. In some cases the language rules (limitations) force developer to create helper types. There are also semi-domain types, like pointers, handles, interators etc. > And I have the same question that Hyman has asked about generics, > plus, Should we emulate inheritance using generics? > should "with type" be mentioned in this context? Interesting, why do you thing it should? -- Regards, Dmitry A. Kazakov www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: How to test object hierarchy 2003-12-20 11:13 ` Dmitry A. Kazakov @ 2003-12-21 4:34 ` Georg Bauhaus 2003-12-21 13:43 ` Dmitry A. Kazakov 0 siblings, 1 reply; 19+ messages in thread From: Georg Bauhaus @ 2003-12-21 4:34 UTC (permalink / raw) Dmitry A. Kazakov <mailbox@dmitry-kazakov.de> wrote: : :> should "with type" be mentioned in this context? : : Interesting, why do you thing it should? I'm not really familiar with "with type", but I thought (guessed) that the OP's procedure could be distributed across pairs of two, each procedure taking one top level class-wide parameter and a derived type parameter. If I have package D is type Root is tagged private; type Derived_1 is new Root with private; procedure Op_1(d: Derived_1; other: Derived_2'Class); -- too early procedure Op_1(d: Derived_2; other: Derived_2'Class); -- too early, too early type Derived_2 is new Root with private; procedure Op_2(d: Derived_2; other: Derived_1'Class); procedure Op_2(d: Derived_1; other: Derived_1'Class); -- too late ... Will "with type" and package reorganisation help? -- Georg ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: How to test object hierarchy 2003-12-21 4:34 ` Georg Bauhaus @ 2003-12-21 13:43 ` Dmitry A. Kazakov 2003-12-21 19:58 ` Dmytry Lavrov 0 siblings, 1 reply; 19+ messages in thread From: Dmitry A. Kazakov @ 2003-12-21 13:43 UTC (permalink / raw) Georg Bauhaus wrote: > Dmitry A. Kazakov <mailbox@dmitry-kazakov.de> wrote: > : > :> should "with type" be mentioned in this context? > : > : Interesting, why do you thing it should? > > I'm not really familiar with "with type", but I thought (guessed) > that the OP's procedure could be distributed across pairs of two, > each procedure taking one top level class-wide parameter and > a derived type parameter. If I have > > package D is > > type Root is tagged private; > > type Derived_1 is new Root with private; > > procedure Op_1(d: Derived_1; other: Derived_2'Class); > -- too early > procedure Op_1(d: Derived_2; other: Derived_2'Class); > -- too early, too early > > type Derived_2 is new Root with private; > > procedure Op_2(d: Derived_2; other: Derived_1'Class); > procedure Op_2(d: Derived_1; other: Derived_1'Class); > -- too late > > ... > > Will "with type" and package reorganisation help? I think that IF Ada should have multiple dispatch on different types then inevitably we should reconsider the freezing rules. The most useful implementations of MD appear when types are defined in different packages. The rationale behind the existing freezing rules is to prevent dispatching to non-elaborated targets. I believe that for a MD operation the freezing point could be the last freezing point of all involved types. For example: package Devices is type Device is tagged ...; procedure Load (X : in out Device); end Device; -- No more primitive operations with only Device with Devices; use Devices; package Curves is type Curve is tagged ...; procedure Show (X : in out Device; Y : Curve); end Curves; -- No more operations with Device and Curve It is clear that these rules can be very dangerous, if we will not limit use of non-primitive operations (except the class-wide ones). The first step could be to make all types "tagged". But even this could be not enough. -- Regards, Dmitry A. Kazakov www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: How to test object hierarchy 2003-12-21 13:43 ` Dmitry A. Kazakov @ 2003-12-21 19:58 ` Dmytry Lavrov 2003-12-22 1:19 ` Robert I. Eachus 2003-12-22 10:05 ` Dmitry A. Kazakov 0 siblings, 2 replies; 19+ messages in thread From: Dmytry Lavrov @ 2003-12-21 19:58 UTC (permalink / raw) "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:<bs47m5$9e9ea$2@ID-77047.news.uni-berlin.de>... <snip> > > I think that IF Ada should have multiple dispatch on different types Wao.That's exactly(multiple dispatch) that i tried to explain to peoples(very experienced and probably smart too ) who know only "object.method" notation. Of course that failed(they even can't understand what it is it), because that damn "."(like fields in record) left place only for one object! i got probably good(and also wild) idea that method(paramether,paramether,...) are shugar for method(composed_class_constructor(paramether1,paramether2,...) ) and if thete's multiple inheritance, it's method(temporary_child_class_constructor(parent1,parent2,...) ); and also about that it's shugar for dispatch(in paramether1[, in paramether2....]).method(in out paramether1[,in out paramether2....]); - it can be implemented without changing the language at all,but need lots of stupid work with "procedural variables". Maybe that could give someone here any good idea. (it was about problem with overloading math operators for classes- double dispathing was required - different methods for matrix by matrix,matrix by scalar,matrix by vector,vector by matrix,etc,in all combinations including complex number stuff ,etc. ) > then > inevitably we should reconsider the freezing rules. The most useful > implementations of MD appear when types are defined in different packages. > The rationale behind the existing freezing rules is to prevent dispatching > to non-elaborated targets. I believe that for a MD operation the freezing > point could be the last freezing point of all involved types. For example: > > package Devices is > type Device is tagged ...; > procedure Load (X : in out Device); > end Device; -- No more primitive operations with only Device > > with Devices; use Devices; > package Curves is > type Curve is tagged ...; > procedure Show (X : in out Device; Y : Curve); > end Curves; -- No more operations with Device and Curve > > It is clear that these rules can be very dangerous, if we will not limit use > of non-primitive operations (except the class-wide ones). The first step > could be to make all types "tagged". But even this could be not enough. Main problem that compiler will no longer detect some errors,right? Regards, Dmytry Lavrov. ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: How to test object hierarchy 2003-12-21 19:58 ` Dmytry Lavrov @ 2003-12-22 1:19 ` Robert I. Eachus 2003-12-22 10:09 ` Dmitry A. Kazakov 2003-12-22 10:05 ` Dmitry A. Kazakov 1 sibling, 1 reply; 19+ messages in thread From: Robert I. Eachus @ 2003-12-22 1:19 UTC (permalink / raw) Dmytry Lavrov wrote: >>I think that IF Ada should have multiple dispatch on different types... In Ada, if and where you need it, you can get multiple dispatching. There are of course many different patterns that correspond to multiple dispatching, and if you want the most general pattern: function "+" (L, R: Object) return Object; Where unlike normal Ada, L, R and the return value can be different specific types. This can be done, but you actually have to do some extra work "under the covers." Normally you would declare the visible "+" as: function "+" (L: Object; R: Object'Class) return Object'Class; Then in the private part you would have a function which is called by the visible "+" but dispatches on the second parameter, and result type: function Add (L: Object'Class; R: Object) return Object; Or L may be of some general representation type. But from experience, doing all this is a lot of work, and you don't want to even think about extending Object beyond the initial set of specific types. You don't have to rethink the entire structure when you do that, but it may be the only way to produce something that is understandable to humans. The Multics PL/I compiler has (had?) a horrible example of this. PL/I has implicit conversions between types and all sorts of conversions you wouldn't expect are defined. Including various flavors of literals, the PL/I compiler front end had 17 different cases to deal with. Well, actually, that was for each parameter. So there were really 289 cases that could come up. In practice only about 60 were implemented specificly, the rest were defaulted by using an "any-to-any" conversion routine on one or the other operand. Most of the defaulted cases involved adding (or whatever operation you were implementing) two literals, so everything could be done at compile time anyway. So can you do something like this in Ada. Sure. Can you maintain your sanity while doing it? Questionable whether you are doing it in Ada, PL/I, assembler, or whatever. The polynomial explosion of cases may be capable of being handled by quite clever code, but you still end up slogging through testing all those bizarre cases anyway. (And in PL/I, you don't have to spend much time dreaming up test cases for adding bit strings to decimal numbers, or adding booleans to character strings before you start screaming. ;-) The much, much, more common, and much easier to deal with case is where you want to dispact separately on two or more independent parameters. I've actually used that. -- Robert I. Eachus "The war on terror is a different kind of war, waged capture by capture, cell by cell, and victory by victory. Our security is assured by our perseverance and by our sure belief in the success of liberty." -- George W. Bush ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: How to test object hierarchy 2003-12-22 1:19 ` Robert I. Eachus @ 2003-12-22 10:09 ` Dmitry A. Kazakov 2003-12-22 17:33 ` Robert I. Eachus 0 siblings, 1 reply; 19+ messages in thread From: Dmitry A. Kazakov @ 2003-12-22 10:09 UTC (permalink / raw) Robert I. Eachus wrote: > Dmytry Lavrov wrote: > >>>I think that IF Ada should have multiple dispatch on different types... > > In Ada, if and where you need it, you can get multiple dispatching. > There are of course many different patterns that correspond to multiple > dispatching, and if you want the most general pattern: > > function "+" (L, R: Object) return Object; > > Where unlike normal Ada, L, R and the return value can be different > specific types. This can be done, but you actually have to do some > extra work "under the covers." > > Normally you would declare the visible "+" as: > > function "+" (L: Object; R: Object'Class) return Object'Class; > > Then in the private part you would have a function which is called by > the visible "+" but dispatches on the second parameter, and result type: > > function Add (L: Object'Class; R: Object) return Object; > > Or L may be of some general representation type. But from experience, > doing all this is a lot of work, and you don't want to even think about > extending Object beyond the initial set of specific types. You don't > have to rethink the entire structure when you do that, but it may be the > only way to produce something that is understandable to humans. This is an argument in favor of implementing MD in Ada, I suppose (:-)) -- Regards, Dmitry A. Kazakov www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: How to test object hierarchy 2003-12-22 10:09 ` Dmitry A. Kazakov @ 2003-12-22 17:33 ` Robert I. Eachus 2003-12-23 10:49 ` Dmitry A. Kazakov 0 siblings, 1 reply; 19+ messages in thread From: Robert I. Eachus @ 2003-12-22 17:33 UTC (permalink / raw) Dmitry A. Kazakov wrote: > This is an argument in favor of implementing MD in Ada, I suppose (:-)) No, it is an argument that current Ada rules are just fine. You can do multiple dispatching in Ada, and the sort of casual dispatching where the author of the code doesn't even know that multiple dispatch is involves works just fine. For example, instantiate a generic with a classwide type or two as an actual type parameter. The resulting executable may have nested dispatching, but there is no real need to anticipate that case when writing the generic. As for cases where you really NEED to understand the code in multiple dispatching terms, these are no harder to program in Ada than in other languages--and no easier. And they really are that hard to wrap the mind around. There are cases which are worth the effort, but precious few. Another more prosaic example would be a general graphic file format converter. I can design such a tool as a combination of a reader and a writer with a standard intermediate representation: ... declare Temp: Intermediate_Format := Read(Input_File); begin Write(Temp, Output_File); end; Of course I can rewrite this as: Write(Read(Input_File), Output_File); Later I might want to add a graphics format that doesn't work well with the "standard" intermediate format. To do this, I can restructure the existing code with a multiple dispatch format: procedure Process(Input: in Graphics_Format; out Graphics_Format'Class); or function Process(Input: Graphics_Format) return Graphics_Format'Class; Now I can provide a body which normally uses the old approach with Intermediate_Format, but first checks for the special cases and handles them with other routines. THAT is when it starts to get difficult to use multiple dispatch. It is not the process of doing what I call 'casual' multiple dispatch in Ada, that is easy. The problem is going through on an N**2 case by case basis (or N**3 or N*M or whatever) and insuring that the approach that is dynamically selected for that particular case is, in some sense, the right one. And when the set of possibilities grows, adding one new format means considering 2N-1 new cases. -- Robert I. Eachus "The war on terror is a different kind of war, waged capture by capture, cell by cell, and victory by victory. Our security is assured by our perseverance and by our sure belief in the success of liberty." -- George W. Bush ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: How to test object hierarchy 2003-12-22 17:33 ` Robert I. Eachus @ 2003-12-23 10:49 ` Dmitry A. Kazakov 0 siblings, 0 replies; 19+ messages in thread From: Dmitry A. Kazakov @ 2003-12-23 10:49 UTC (permalink / raw) Robert I. Eachus wrote: > Dmitry A. Kazakov wrote: > >> This is an argument in favor of implementing MD in Ada, I suppose (:-)) > > No, it is an argument that current Ada rules are just fine. You can do > multiple dispatching in Ada, and the sort of casual dispatching where > the author of the code doesn't even know that multiple dispatch is > involves works just fine. For example, instantiate a generic with a > classwide type or two as an actual type parameter. The resulting > executable may have nested dispatching, but there is no real need to > anticipate that case when writing the generic. These cases are not cases of MD. Anything that can be written using "cascading" dispatch is in fact single dispatch in one argument and class-wide in another. What is not MD, is not. > As for cases where you really NEED to understand the code in multiple > dispatching terms, these are no harder to program in Ada than in other > languages--and no easier. And they really are that hard to wrap the > mind around. There are cases which are worth the effort, but precious > few. The point is that MD is a *natural* view on any subprogam having many parameters. All other views are in fact kludges, hard to understand and very error-prone. Note that if the language is aware of MD, it can enforce necessary overridings, because it knows that they should be. Otherwise, a developer is exposed to a geometric explosion of variants, which he might be even unaware of, especially if he derives from a library type. > Another more prosaic example would be a general graphic file format > converter. I can design such a tool as a combination of a reader and a > writer with a standard intermediate representation: > > ... > declare > Temp: Intermediate_Format := Read(Input_File); > begin > Write(Temp, Output_File); > end; > > Of course I can rewrite this as: > > Write(Read(Input_File), Output_File); > > Later I might want to add a graphics format that doesn't work well with > the "standard" intermediate format. To do this, I can restructure the > existing code with a multiple dispatch format: > > procedure Process(Input: in Graphics_Format; out Graphics_Format'Class); > or > function Process(Input: Graphics_Format) return Graphics_Format'Class; > > Now I can provide a body which normally uses the old approach with > Intermediate_Format, but first checks for the special cases and handles > them with other routines. > > THAT is when it starts to get difficult to use multiple dispatch. It is > not the process of doing what I call 'casual' multiple dispatch in Ada, > that is easy. The problem is going through on an N**2 case by case > basis (or N**3 or N*M or whatever) and insuring that the approach that > is dynamically selected for that particular case is, in some sense, the > right one. And when the set of possibilities grows, adding one new > format means considering 2N-1 new cases. Right, therefore it has to be supported by the compiler! And in this case, MD on same type hierarchy, it is pretty easy to do. The compiler shall simply check that if one of 2N-1 possible overridings happens, others have to be explicitly overridden too. Also I really wish some language support for commutative operations, which would reduce the number of variants in twice. But the real problem with MD is the case of different type hierarchies. For example, stream attributes. Present implementation is obviously inconsistent. S'Write should know all stream types because it is class-wide in the Stream argument. How a developer of a type can foresee all possible streams? What if it is a library type? It is clear to me that consistency should be enforced by the language. The great problem is how. -- Regards, Dmitry A. Kazakov www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: How to test object hierarchy 2003-12-21 19:58 ` Dmytry Lavrov 2003-12-22 1:19 ` Robert I. Eachus @ 2003-12-22 10:05 ` Dmitry A. Kazakov 1 sibling, 0 replies; 19+ messages in thread From: Dmitry A. Kazakov @ 2003-12-22 10:05 UTC (permalink / raw) Dmytry Lavrov wrote: > "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message > news:<bs47m5$9e9ea$2@ID-77047.news.uni-berlin.de>... <snip> >> >> I think that IF Ada should have multiple dispatch on different types > > Wao.That's exactly(multiple dispatch) that i tried to explain to > peoples(very experienced and probably smart too ) who know only > "object.method" notation. > Of course that failed(they even can't understand what it is it), > because that damn "."(like fields in record) left place only for one > object! > > i got probably good(and also wild) idea that > method(paramether,paramether,...) are shugar for > method(composed_class_constructor(paramether1,paramether2,...) ) > > and if thete's multiple inheritance, it's > method(temporary_child_class_constructor(parent1,parent2,...) ); > > and also about that it's shugar for > dispatch(in paramether1[, in paramether2....]).method(in out > paramether1[,in out paramether2....]); > - it can be implemented without changing the language at all,but need > lots of stupid work with "procedural variables". > > Maybe that could give someone here any good idea. > > (it was about problem with overloading math operators for classes- > double dispathing was required - different methods for matrix by > matrix,matrix by scalar,matrix by vector,vector by matrix,etc,in all > combinations including complex number stuff ,etc. ) The case you are describing is multiple dispatch on same type. It is a bit easier, especially because the existing freezing rules are OK and because it still allows C++ appoach of having virtual table pointer buried in objects. I have posted an example how to deal with it. You can also take a look at http://www.dmitry-kazakov.de/ada/components.htm where it is used for "=", "<" operations. But the pet idea of many OOPLs that methods belong to object is absolutely wrong. So the prefix notation. The pressure is so high that there is an AI to introduce it in Ada! (It already exists for tasks and protected objects) >> then >> inevitably we should reconsider the freezing rules. The most useful >> implementations of MD appear when types are defined in different >> packages. The rationale behind the existing freezing rules is to prevent >> dispatching to non-elaborated targets. I believe that for a MD operation >> the freezing point could be the last freezing point of all involved >> types. For example: >> >> package Devices is >> type Device is tagged ...; >> procedure Load (X : in out Device); >> end Device; -- No more primitive operations with only Device >> >> with Devices; use Devices; >> package Curves is >> type Curve is tagged ...; >> procedure Show (X : in out Device; Y : Curve); >> end Curves; -- No more operations with Device and Curve >> >> It is clear that these rules can be very dangerous, if we will not limit >> use of non-primitive operations (except the class-wide ones). The first >> step could be to make all types "tagged". But even this could be not >> enough. > > Main problem that compiler will no longer detect some errors,right? Errors, undesired overloadings, where overriding was meant, backward compatibility all that things. -- Regards, Dmitry A. Kazakov www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: How to test object hierarchy 2003-12-18 18:24 How to test object hierarchy Pierre Favier 2003-12-19 0:15 ` Stephen Leake 2003-12-19 10:53 ` Dmitry A. Kazakov @ 2003-12-19 17:24 ` Nick Roberts 2 siblings, 0 replies; 19+ messages in thread From: Nick Roberts @ 2003-12-19 17:24 UTC (permalink / raw) Pierre Favier wrote: > I am wondering how to test for two objects which types both derive from > a common root type if one of them derives from the other. In short, I am > trying to run something like the following code which does not compile > because the Class attribute applies to types or subtypes but not to > objects ... > > Any suggestions on how to achieve the intended effect? I feel this is a bit like someone asking how to scratch his ear with his foot. I suspect the most sensible answer might be "Don't do that." Since, within the procedure Test_Hierarchy, the only operations available for either Obj1 or Obj2 are the operations of the type Root_Object, how can it be of any significance to the code inside this procedure what relation (deeper in the hierarchy) the objects have to each other? Surely the code inside the procedure sees only two objects which obey the interface of Root_Object? I would guess, therefore, that there is an error of logic (or perhaps of style) in your program, but if you think not then by all means please give more details of what you are really trying to do. -- Nick Roberts __________________________________________________________ | Fight Spam! Join EuroCAUCE: http://www.euro.cauce.org/ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2003-12-23 10:49 UTC | newest] Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2003-12-18 18:24 How to test object hierarchy Pierre Favier 2003-12-19 0:15 ` Stephen Leake 2003-12-19 7:45 ` Pierre Favier 2003-12-19 10:53 ` Dmitry A. Kazakov 2003-12-19 14:35 ` Hyman Rosen 2003-12-19 17:07 ` Dmitry A. Kazakov 2003-12-19 23:26 ` Robert A Duff 2003-12-20 18:20 ` Robert I. Eachus 2003-12-19 17:25 ` Georg Bauhaus 2003-12-20 11:13 ` Dmitry A. Kazakov 2003-12-21 4:34 ` Georg Bauhaus 2003-12-21 13:43 ` Dmitry A. Kazakov 2003-12-21 19:58 ` Dmytry Lavrov 2003-12-22 1:19 ` Robert I. Eachus 2003-12-22 10:09 ` Dmitry A. Kazakov 2003-12-22 17:33 ` Robert I. Eachus 2003-12-23 10:49 ` Dmitry A. Kazakov 2003-12-22 10:05 ` Dmitry A. Kazakov 2003-12-19 17:24 ` Nick Roberts
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox