* Tagged type more type safe than access to subprogram ?
@ 2009-10-28 7:51 Hibou57 (Yannick Duchêne)
2009-10-28 8:55 ` Dmitry A. Kazakov
0 siblings, 1 reply; 6+ messages in thread
From: Hibou57 (Yannick Duchêne) @ 2009-10-28 7:51 UTC (permalink / raw)
Hello Ada Artists,
I was reading the Ada 95 Quality and Style Guide, seeking for some
inspiration about a design / style doubt.
I came into Chapter 5, “ CHAPTER 5: Programming Practices ”,
5.3.4 Subprogram Access Types says :
> You can achieve the same effect as access-to-subprogram types for
> dynamic selection by using abstract tagged types. You declare an
> abstract type with one abstract operation and then use an
> access-to-class-wide type to get the dispatching effect. This technique
> provides greater flexibility and type safety than access-to-subprogram types
Here : http://www.iste.uni-stuttgart.de/ps/ada-doc/style_guide/sec_5a.html#5.3.4
I agree about the “ greater flexibility” (I've recently meet such a
case), but I do not understand the “ and [greater] type safety ”.
If it's Ok for me to assert that tagged type is a more flexible way
than access to subprogram, I do not see a case where access to
subprogram would be less type safe than tagged type.
If there is something I do not understand, this may means I have
something to learn about it (the purpose of the question then).
Does any one know a case which match this assertion ?
Have a nice October day
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Tagged type more type safe than access to subprogram ? 2009-10-28 7:51 Tagged type more type safe than access to subprogram ? Hibou57 (Yannick Duchêne) @ 2009-10-28 8:55 ` Dmitry A. Kazakov 2009-10-29 11:00 ` Hibou57 (Yannick Duchêne) 0 siblings, 1 reply; 6+ messages in thread From: Dmitry A. Kazakov @ 2009-10-28 8:55 UTC (permalink / raw) On Wed, 28 Oct 2009 00:51:19 -0700 (PDT), Hibou57 (Yannick Duchêne) wrote: > Hello Ada Artists, > > I was reading the Ada 95 Quality and Style Guide, seeking for some > inspiration about a design / style doubt. > > I came into Chapter 5, “ CHAPTER 5: Programming Practices ”, > > 5.3.4 Subprogram Access Types says : >> You can achieve the same effect as access-to-subprogram types for >> dynamic selection by using abstract tagged types. You declare an >> abstract type with one abstract operation and then use an >> access-to-class-wide type to get the dispatching effect. This technique >> provides greater flexibility and type safety than access-to-subprogram types > Here : http://www.iste.uni-stuttgart.de/ps/ada-doc/style_guide/sec_5a.html#5.3.4 > > I agree about the “ greater flexibility” (I've recently meet such a > case), but I do not understand the “ and [greater] type safety ”. > > If it's Ok for me to assert that tagged type is a more flexible way > than access to subprogram, I do not see a case where access to > subprogram would be less type safe than tagged type. > > If there is something I do not understand, this may means I have > something to learn about it (the purpose of the question then). > > Does any one know a case which match this assertion ? An access to subprogram is a poor-man's closure. Let's ignore "access" part and consider a pure downward closure (as it should have been in Ada). I argue that a helper type with an abstract primitive subprogram is safer than a closure, both safer and type-safer. The general safety comes from the fact that a closure brings a context with it, which an object normally does not. An abstract type is better encapsulated and there is less chances to run into occasional side effects. Even if the side effects are desired I would argue that it is better and safer to limit them to the object rather than to the closure's context. The crucial point is that closure's effects are "there", while effects on the object are localized to the object's state, there are "here", at the call point. The type safety is gained through different types derived from the abstract parent. There might be no difference at the caller side, e.g. whether you mistakenly call to the closure C1 instead of C2, or mistakenly pass an instance of S1 instead of S2 (both from the S'Class). Yet it is type safer with regard to the parameters required to construct S2. Its constructor can have a different signature, so that the parameters you pass in order to create it were different from S1. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Tagged type more type safe than access to subprogram ? 2009-10-28 8:55 ` Dmitry A. Kazakov @ 2009-10-29 11:00 ` Hibou57 (Yannick Duchêne) 2009-10-29 17:54 ` Dmitry A. Kazakov 0 siblings, 1 reply; 6+ messages in thread From: Hibou57 (Yannick Duchêne) @ 2009-10-29 11:00 UTC (permalink / raw) On 28 oct, 09:55, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de> wrote: > An access to subprogram is a poor-man's closure. Let's ignore "access" part > and consider a pure downward closure (as it should have been in Ada). “ As this should have been in Ada ” ? What were you to mean ? I've always though real closures are not possible with such structures as Ada provides, except at package level — which is especially the case when a package can have multiple instances... but only at package level. Isn't it ? > I argue that a helper type with an abstract primitive subprogram is safer > than a closure, both safer and type-safer. > > The general safety comes from the fact that a closure brings a context with > it, which an object normally does not. An abstract type is better > encapsulated and there is less chances to run into occasional side effects. > Even if the side effects are desired I would argue that it is better and > safer to limit them to the object rather than to the closure's context. The > crucial point is that closure's effects are "there", while effects on the > object are localized to the object's state, there are "here", at the call > point. > > The type safety is gained through different types derived from the abstract > parent. There might be no difference at the caller side, e.g. whether you > mistakenly call to the closure C1 instead of C2, or mistakenly pass an > instance of S1 instead of S2 (both from the S'Class). Yet it is type safer > with regard to the parameters required to construct S2. Its constructor can > have a different signature, so that the parameters you pass in order to > create it were different from S1. If I attempt an abstract of your words, and if I've understood you in a right way, it could be : tagged types are safer than accesses to subprograms, because the abstract method of a tagged type is always associated to a suitable context, unlike subprogram, with which ones a single error is immediately turned into a double error — the one about the subprogram and the one about the closure which comes with the subprogram reference. This is relevant, indeed. Now I see the deal much better (providing I'm OK with my understanding). I would like to just add two other notes, about flexibility (not safety) : the first one, I think its a good idea to add a Ready function (returning Boolean) to the tagged type, because the tagged type may be extended in a way where it needs setup (useful for peoples who like to add Eiffel-like precondition to their specifications). This seems general enough to me to add this function to any tagged type which is intended to act as an abstract method (and to add an initial default implementation which always return True). And then, about implementation now : if an abstract method is concerned by performance, it is possible to add an alternate batch version belong to the primary abstract method (to run the method on a sequence of parameters, either as input or output). This is a good idea to add it to the same tagged type, as it is deeply related to the “ normal ” (un- batched version) of the abstract method (deeply related in many ways, such as required internal data to work, setup, shared part of algorithm, etc). This is another argument pleading in favor of the provided flexible of tagged types over access to subprograms. ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Tagged type more type safe than access to subprogram ? 2009-10-29 11:00 ` Hibou57 (Yannick Duchêne) @ 2009-10-29 17:54 ` Dmitry A. Kazakov 2009-10-29 20:45 ` Georg Bauhaus 0 siblings, 1 reply; 6+ messages in thread From: Dmitry A. Kazakov @ 2009-10-29 17:54 UTC (permalink / raw) On Thu, 29 Oct 2009 04:00:29 -0700 (PDT), Hibou57 (Yannick Duchêne) wrote: > On 28 oct, 09:55, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de> > wrote: >> An access to subprogram is a poor-man's closure. Let's ignore "access" part >> and consider a pure downward closure (as it should have been in Ada). > “ As this should have been in Ada ” ? What were you to mean ? I've > always though real closures are not possible with such structures as > Ada provides, except at package level — which is especially the case > when a package can have multiple instances... but only at package > level. Isn't it ? I meant downward closures. There is no reason for type P is access procedure (...); where actually meant type P is procedure (...); It is almost always safer and cleaner to pass subprograms instead of access to them. Obviously a subprogram type were a limited type, so a subprogram were passed by reference. A pointer were only needed when you wanted to copy it. And copying pointers is always asking for trouble... BTW, in Ada 83, there waa no access to subprogram, so we used tasks instead (where a subprogram had to be a non-generic parameter). Task is a proper type since the day one. Subprograms lingered, but then in Ada 95 one did a big mistake introducing access discriminants, access to subprogram, access to self (the Rosen trick), access to function's mutable parameter etc. And almost in all use cases of these, no access is actually needed. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Tagged type more type safe than access to subprogram ? 2009-10-29 17:54 ` Dmitry A. Kazakov @ 2009-10-29 20:45 ` Georg Bauhaus 2009-10-30 8:25 ` Dmitry A. Kazakov 0 siblings, 1 reply; 6+ messages in thread From: Georg Bauhaus @ 2009-10-29 20:45 UTC (permalink / raw) Dmitry A. Kazakov schrieb: > On Thu, 29 Oct 2009 04:00:29 -0700 (PDT), Hibou57 (Yannick Duchêne) wrote: > >> On 28 oct, 09:55, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de> >> wrote: >>> An access to subprogram is a poor-man's closure. Let's ignore "access" part >>> and consider a pure downward closure (as it should have been in Ada). > >> “ As this should have been in Ada ” ? What were you to mean ? I've >> always though real closures are not possible with such structures as >> Ada provides, except at package level — which is especially the case >> when a package can have multiple instances... but only at package >> level. Isn't it ? > > I meant downward closures. [...] > BTW, in Ada 83, there waa no access to subprogram, so we used tasks instead > (where a subprogram had to be a non-generic parameter). Tagged types may come close to a solution sometimes. You make "function objects", like the ones found in Eiffel and, I think, some other languages. Make it have an Item primitive operation that returns the functions value at that point: package F is type Nums is range 1 .. 3_333; type Func_Of_1_Nums is abstract tagged private; function Item (F : Func_Of_1_Nums; X1 : Nums) return Nums is abstract; -- value of function at X1 type Func_Of_2_Nums is abstract tagged private; function Curry (F : Func_Of_2_Nums; First_Argument: Nums) return Func_Of_1_Nums'Class is abstract; function Item (F : Func_Of_2_Nums; X1, X2 : Nums) return Nums is abstract; -- value of function at (X1, X2) private type Func_Of_1_Nums is abstract tagged record null; -- ... others, e.g. a memoizing cache end record; type Func_Of_2_Nums is Abstract tagged record null; end record; end F; package F.Addition is type Adding_Function is new Func_Of_2_Nums with null record; overriding function Curry (F: Adding_Function; First_Argument: Nums) return Func_Of_1_Nums'Class; overriding function Item (F : Adding_Function; X1, X2: Nums) return Nums; end F.Addition; with F.Addition; use F; procedure Test_F is Sum : Addition.Adding_Function; Add_2 : constant Func_Of_1_Nums'Class := Addition.Curry (Sum, First_Argument => 2); Result : Nums; type List_Of_Nums is array (Positive range <>) of Nums; ---------------------------------------------- -- This is the important bit: can pass -- a "function object", To_Be_Applied, -- to Update_All ---------------------------------------------- procedure Update_All (To_Be_Applied : Func_Of_1_Nums'Class; Some_Numbers: in out List_Of_Nums) is separate; Three_Numbers : List_Of_Nums (1 .. 3) := (40, 664, 1064); begin Result := Sum.Item (X1 => 3, X2 => 2); pragma Assert (Result = 5); Result := Add_2.Item (X1 => 3); pragma Assert (Result = 5); Update_All (To_Be_Applied => Add_2, Some_Numbers => Three_Numbers); pragma Assert (Three_Numbers = (42, 666, 1066)); end Test_F; package body F.Addition is type Curried_Of_2 is new Func_Of_1_Nums with record X1 : Nums; end record; type Func_Of_1_Nums_Ref is access Func_Of_1_Nums'Class; overriding function Item (F: Curried_Of_2; X2 : Nums) return Nums is -- add F.X1 (which is bound after Curry-ing) begin return F.X1 + X2; end Item; function Curry (F: Adding_Function; First_Argument: Nums) return Func_Of_1_Nums'Class is Result : constant Func_Of_1_Nums_Ref := new Curried_Of_2'(X1 => First_Argument); begin return Result.all; end Curry; overriding function Item (F: Adding_Function; X1, X2: Nums) return Nums is -- sum begin return X1 + X2; end Item; end F.Addition; separate (Test_F) procedure Update_All (To_Be_Applied : Func_Of_1_Nums'Class; Some_Numbers: in out List_Of_Nums) is begin for K in Some_Numbers'Range loop Some_Numbers (K) := To_Be_Applied.Item (Some_Numbers (K)); end loop; end Update_All; ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Tagged type more type safe than access to subprogram ? 2009-10-29 20:45 ` Georg Bauhaus @ 2009-10-30 8:25 ` Dmitry A. Kazakov 0 siblings, 0 replies; 6+ messages in thread From: Dmitry A. Kazakov @ 2009-10-30 8:25 UTC (permalink / raw) On Thu, 29 Oct 2009 21:45:02 +0100, Georg Bauhaus wrote: > Dmitry A. Kazakov schrieb: >> On Thu, 29 Oct 2009 04:00:29 -0700 (PDT), Hibou57 (Yannick Duchêne) wrote: >> >>> On 28 oct, 09:55, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de> >>> wrote: >>>> An access to subprogram is a poor-man's closure. Let's ignore "access" part >>>> and consider a pure downward closure (as it should have been in Ada). >> >>> “ As this should have been in Ada ” ? What were you to mean ? I've >>> always though real closures are not possible with such structures as >>> Ada provides, except at package level — which is especially the case >>> when a package can have multiple instances... but only at package >>> level. Isn't it ? >> >> I meant downward closures. [...] > >> BTW, in Ada 83, there waa no access to subprogram, so we used tasks instead >> (where a subprogram had to be a non-generic parameter). > > Tagged types may come close to a solution sometimes. Yes, I am using this pattern very often. But: 1. There were no tagged types in Ada 83 2. In Ada 95 tagged types were in effect strictly library-level. This restriction was lifted only in Ada 2005, too late to stop the "access-to everything cancer". 3. The language is too heavy when it comes to create a singleton object overriding one or two abstract primitive operations. There should be short-cuts for that. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2009-10-30 8:25 UTC | newest] Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2009-10-28 7:51 Tagged type more type safe than access to subprogram ? Hibou57 (Yannick Duchêne) 2009-10-28 8:55 ` Dmitry A. Kazakov 2009-10-29 11:00 ` Hibou57 (Yannick Duchêne) 2009-10-29 17:54 ` Dmitry A. Kazakov 2009-10-29 20:45 ` Georg Bauhaus 2009-10-30 8:25 ` Dmitry A. Kazakov
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox