comp.lang.ada
 help / color / mirror / Atom feed
* 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