comp.lang.ada
 help / color / mirror / Atom feed
* Re-exporting primitive operations of a private type (like "-", and 'min)
@ 2005-10-29 21:19 Anonymous Coward
  2005-10-30  8:57 ` Dmitry A. Kazakov
  2005-10-30  9:18 ` Jeffrey R. Carter
  0 siblings, 2 replies; 17+ messages in thread
From: Anonymous Coward @ 2005-10-29 21:19 UTC (permalink / raw)


I'm bothered by the fact that the primitive operations of a parent are
not inherited in a private type.  In particular, the basic arithmetic
operations are lost, like "+", "-", 'min, 'max, etc.  There seems to
be no clean way to re-export these operations, or am I missing
something?  Here is some sample code:

[distance.ads]

   package Distance is

      type Public_Distance_Type is new Float;

      procedure Some_Procedure 
        (Sample_Variable : in Public_Distance_Type);


      type Private_Distance_Type is private;

      Zero_Distance  : constant Private_Distance_Type;
      Large_Distance : constant Private_Distance_Type;

      function "-" (Left, Right : in Private_Distance_Type)
        return Private_Distance_Type;

   private

      type Private_Distance_Type is new Public_Distance_Type;

      Zero_Distance  : constant Private_Distance_Type := 0.0;
      Large_Distance : constant Private_Distance_Type := 999_999_999.0;

   end Distance;

[distance.adb]

   package body Distance is

      function "-" (Left, Right : in Private_Distance_Type)
        return Private_Distance_Type is

      begin

         --This is ugly.  Isn't there a way to declare this
         --operation without redefining it?  The type casting
         --is also a nuissance, but the compiler warns of
         --infinite loops if casting is not used.

         return Private_Distance_Type(Public_Distance_Type(Left) -
                                      Public_Distance_Type(Right));

      end "-";

      procedure Some_Procedure (Sample_Variable : in Public_Distance_Type)is
      begin

         --This was another simple test to see whether we can
         --inherit explicitly declared public operations.

         null;

      end Some_Procedure;

   end Distance;

[use_distance.adb]

   with Distance;

   procedure Use_Distance is

      Public_Distance  : Distance.Public_Distance_Type;
      Private_Distance : Distance.Private_Distance_Type;

      use type Distance.Private_Distance_Type;
      use type Distance.Public_Distance_Type;

   begin

      Public_Distance := Distance.Public_Distance_Type'Min(-5.0,7.0);

      --The following line fails to compile because
      --'min is not inherited.
      --
      --Private_Distance := Distance.Private_Distance_Type'Min
      --  (Distance.Zero_Distance,Distance.Large_Distance);

      Distance.Some_Procedure (Sample_Variable => Public_Distance);

      --The following line fails to compile because
      --Some_Procedure is not inherited.
      --
      --Distance.Some_Procedure (Sample_Variable => Private_Distance);

      --This line compiles because it was redefined explicitly
      --
      Private_Distance := Distance.Large_Distance -
                          Distance.Zero_Distance;

   end Use_Distance;

---

Redefining "-" is an annoyance.  I'm not even sure how to redefine
attribute operations like 'min.  Suggestions?



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Re-exporting primitive operations of a private type (like "-", and 'min)
  2005-10-29 21:19 Re-exporting primitive operations of a private type (like "-", and 'min) Anonymous Coward
@ 2005-10-30  8:57 ` Dmitry A. Kazakov
  2005-10-30  9:18 ` Jeffrey R. Carter
  1 sibling, 0 replies; 17+ messages in thread
From: Dmitry A. Kazakov @ 2005-10-30  8:57 UTC (permalink / raw)


On Sat, 29 Oct 2005 21:19:27 GMT, Anonymous Coward wrote:

> I'm bothered by the fact that the primitive operations of a parent are
> not inherited in a private type.

They are but in the view where inheritance happens. In your example it
happens in the private view.

> In particular, the basic arithmetic
> operations are lost, like "+", "-", 'min, 'max, etc.

"+' and "-" are rather hidden.

> There seems to
> be no clean way to re-export these operations,

Yep. That's because the original operation cannot be named. Otherwise, one
could just rename new "-" to the old one. As for attributes, it is another
case, they cannot be user-defined at all.

> Redefining "-" is an annoyance.

In general, the problem is that old-fashioned way emerged before Ada became
OO. Private_Distance_Type is a numeric type. That should be its *public*
contract. But in Ada it is impossible to specify things like this for
non-tagged types [outside generics, to be precise.] The compiler cannot
recognize the programmer's intent from a bunch of operations declared in
the public part. So it does not. Therefore when in the private part
Private_Distance_Type gets implemented as a clone of a numeric type, the
compiler treats public "-" as a different operation declared.

[ I'm not sure if interfaces of Ada 2005 might help here. Let's wait for a
working compiler. ]

Anyway, you could go this way:

   ...
private
   type Most_Private_Distance_Type is new Public_Distance_Type;
   function Sub (Left, Right : in Most_Private_Distance_Type)
      return Most_Private_Distance_Type renames "-";
       -- Renaming "as-declaration" creates a new primitive operation Sub

   type Private_Distance_Type is new Most_Private_Distance_Type;
       -- Both "-" and Sub are inherited, but "-" gets hidden by "-"
       -- declared in the public part

   function "-" (Left, Right : in Private_Distance_Type)
      return Private_Distance_Type renames Sub;
       -- Renaming "as-body" implements public "-" through private "-"
       -- via Sub

Warning, this may crash GNAT 3.15p which has many bugs in visibility rules
(let language lawyers correct me if I'm wrong and the above is illegal.) I
didn't try such things with GNAT GPL but it is even more buggy. (:-()

> I'm not even sure how to redefine
> attribute operations like 'min.  Suggestions?

They aren't "normal" operations, as they should be, so forget about them.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Re-exporting primitive operations of a private type (like "-", and 'min)
  2005-10-29 21:19 Re-exporting primitive operations of a private type (like "-", and 'min) Anonymous Coward
  2005-10-30  8:57 ` Dmitry A. Kazakov
@ 2005-10-30  9:18 ` Jeffrey R. Carter
  2005-10-30 14:16   ` Martin Krischik
  2005-10-31  4:15   ` Anonymous Coward
  1 sibling, 2 replies; 17+ messages in thread
From: Jeffrey R. Carter @ 2005-10-30  9:18 UTC (permalink / raw)


Anonymous Coward wrote:
>       --The following line fails to compile because
>       --'min is not inherited.
>       --
>       --Private_Distance := Distance.Private_Distance_Type'Min
>       --  (Distance.Zero_Distance,Distance.Large_Distance);
> 
>       Distance.Some_Procedure (Sample_Variable => Public_Distance);
> 
>       --The following line fails to compile because
>       --Some_Procedure is not inherited.
>       --
>       --Distance.Some_Procedure (Sample_Variable => Private_Distance);

The whole point of private types is that the only visible operations on them are 
assignment, equality and inequality, and any explicitly defined operations in 
the visible part of the package specification. Thus, 'Min is not defined for the 
type because it is not visibly a numeric or enumeration type. Some_Procedure is 
not defined for the type because you did not define such a procedure for the 
type. "-" is defined only because you did define "-" for the type, not because 
of its full type definition. You can have any full type definition for the type 
that allows assignment and equality. It could be an array of records.

Again, the only visible operations for the type are assignment, equality, and 
those explicitly defined in the package. The full type declaration is not 
visible, and the fact that it gives the type certain operations not declared in 
the package specification does not change the set of visible operations. Those 
additional operations are only visible where the full type definition is visible.

Another way of saying this is that the full type definition has no effect on the 
client's view of the type.

> Redefining "-" is an annoyance.  I'm not even sure how to redefine
> attribute operations like 'min.  Suggestions?

Redefining a predefined operation such as "-" *is* a pain. The problem is that 
once you declare "-" for the type, that declaration hides the predefined 
operation, and there's no way to refer to the predefined operation after that. 
That's why you have to convert to a suitable numeric type, invoke the equivalent 
operation for that type, and then convert back to the private type.

(Note that "casting" is not an Ada term. I presume from context that you were 
referring to type conversions.)

However, you only have to define the operations once, so it's a limited amount 
of pain.

It might be nice to have a way to define opaque numeric types, but, for better 
or worse, that's not a path that Ada took. It's lack is most often felt in 
defining generics. There are situations in which a generic could operate on any 
numeric type. Ada has no easy way to define such a generic.

-- 
Jeff Carter
"C++ is like jamming a helicopter inside a Miata
and expecting some sort of improvement."
Drew Olbrich
51



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Re-exporting primitive operations of a private type (like "-", and 'min)
  2005-10-30  9:18 ` Jeffrey R. Carter
@ 2005-10-30 14:16   ` Martin Krischik
  2005-10-30 22:35     ` Robert A Duff
  2005-10-31  4:15   ` Anonymous Coward
  1 sibling, 1 reply; 17+ messages in thread
From: Martin Krischik @ 2005-10-30 14:16 UTC (permalink / raw)


Am 30.10.2005, 11:18 Uhr, schrieb Jeffrey R. Carter <spam@spam.com>:

> That's why you have to convert to a suitable numeric type, invoke the  
> equivalent operation for that type, and then convert back to the private  
> type.

Would 'Base not be a suitable type?

Martin



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Re-exporting primitive operations of a private type (like "-", and 'min)
  2005-10-30 14:16   ` Martin Krischik
@ 2005-10-30 22:35     ` Robert A Duff
  0 siblings, 0 replies; 17+ messages in thread
From: Robert A Duff @ 2005-10-30 22:35 UTC (permalink / raw)


"Martin Krischik" <krischik@users.sourceforge.net> writes:

> Am 30.10.2005, 11:18 Uhr, schrieb Jeffrey R. Carter <spam@spam.com>:
> 
> > That's why you have to convert to a suitable numeric type, invoke the
> > equivalent operation for that type, and then convert back to the
> > private  type.
> 
> Would 'Base not be a suitable type?

No, T'Base returns a subtype, but it's same _type_ as T.
So whatever operations you do will be those of T.

- Bob



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Re-exporting primitive operations of a private type (like "-", and 'min)
  2005-10-30  9:18 ` Jeffrey R. Carter
  2005-10-30 14:16   ` Martin Krischik
@ 2005-10-31  4:15   ` Anonymous Coward
  2005-10-31  4:34     ` Anonymous Coward
                       ` (2 more replies)
  1 sibling, 3 replies; 17+ messages in thread
From: Anonymous Coward @ 2005-10-31  4:15 UTC (permalink / raw)


> The whole point of private types is that the only visible operations
> on them are assignment, equality and inequality, and any explicitly
> defined operations in the visible part of the package
> specification. 

That makes sense.  As a default, it probably would be a poor language
design to have private types automatically export public primitive
operations.  If I created an Altitude_Type, I wouldn't want to inherit
the "+" operation.  However, I was hoping for a one liner (or a
pragma) that would enable me to explicitly declare operations for
public use.  The fact that these must be redefined really seems like a
short-coming of the language.

Anyway, it's not the end of the world.  I mainly just wanted to get an
idea for cleanest way to handle this dirty situation.. and I like the
suggestions you folks made.  I appreciate all your advice.  I haven't
decided which approach I like better, but here's what my sample code
looks like right now:

[distance.ads]

   package Distance is

      type Public_Distance_Type is new Float;

      type Private_Distance_Type is private;

      Zero_Distance  : constant Private_Distance_Type;
      Large_Distance : constant Private_Distance_Type;

      function "-" (Left, Right : in Private_Distance_Type)
        return Private_Distance_Type;

      function "+" (Left, Right : in Private_Distance_Type)
        return Private_Distance_Type;

   private

      type Private_Distance_Type is new Public_Distance_Type;

      Zero_Distance  : constant Private_Distance_Type := 0.0;
      Large_Distance : constant Private_Distance_Type := 999_999_999.0;

   end Distance;

[distance.adb]

   package body Distance is

      -- Implementation operations ------------------------------------------------

      function Subtract (Left, Right : in Private_Distance_Type)
        return Private_Distance_Type is

      begin

         --Kazakov's suggested approach.  This is good because it's
         --simple, and doesn't require type conversions.  
         --(May not work with gnat 3.15p)

         return (Left - Right);

      end Subtract;

      -- Public operations --------------------------------------------------------

      function "-" (Left, Right : in Private_Distance_Type)
        return Private_Distance_Type renames Subtract;


      function "+" (Left, Right : in Private_Distance_Type)
        return Private_Distance_Type is

      begin

         --Krischik's suggested approach.  This is better than what I
         --had started with because I don't need to reference the
         --parent type explicitly.

         return Private_Distance_Type(Private_Distance_Type'Base(Left) -
                                      Private_Distance_Type'Base(Right));

      end "+";

   end Distance;

[use_distance.adb]

   with Distance;

   procedure Use_Distance is

      Public_Distance  : Distance.Public_Distance_Type;
      Private_Distance : Distance.Private_Distance_Type;

      use type Distance.Private_Distance_Type;
      use type Distance.Public_Distance_Type;

   begin

      --This operation is forever invisible in the
      --Private_Distance_Type, and can only be declared as an
      --operation with a new name.
      --
      Public_Distance := Distance.Public_Distance_Type'Min(-5.0,7.0);

      --These lines compile only because they are redefined
        explicitly, using function overloading.
      --
      Private_Distance := Distance.Large_Distance -
                          Distance.Zero_Distance;

      Private_Distance := Distance.Large_Distance +
                          Distance.Zero_Distance;

   end Use_Distance;

---

In my real life case, there is no Public_Distance_Type.  It's really
just derived from a Float, but I use it here for clarity and testing
purposes.  



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Re-exporting primitive operations of a private type (like "-", and 'min)
  2005-10-31  4:15   ` Anonymous Coward
@ 2005-10-31  4:34     ` Anonymous Coward
  2005-10-31  6:14     ` Jeffrey R. Carter
  2005-10-31  8:27     ` Niklas Holsti
  2 siblings, 0 replies; 17+ messages in thread
From: Anonymous Coward @ 2005-10-31  4:34 UTC (permalink / raw)


Oops, I posted too soon.  That code for "-" compiles, but gives a
segmentation fault when it runs.  Could it be the problem Kazakov
warned of in 3.15p?  Here is my version:

   # rpm -qi gcc
   Name        : gcc                          Relocations: (not relocateable)
   Version     : 3.2.2                             Vendor: Red Hat, Inc.
   Release     : 5                             Build Date: Tue 25 Feb 2003 06:53:15 AM MST
   Install Date: Thu 24 Jul 2003 05:55:48 AM MDT      Build Host: stripples.devel.redhat.com
   Group       : Development/Languages         Source RPM: gcc-3.2.2-5.src.rpm
   Size        : 11592745                         License: GPL
   Signature   : DSA/SHA1, Tue 25 Feb 2003 08:04:13 AM MST, Key ID 219180cddb42a60e
   Packager    : Red Hat, Inc. <http://bugzilla.redhat.com/bugzilla>
   URL         : http://gcc.gnu.org
   Summary     : The GNU cc and gcc C compilers.
   Description :
   The gcc package includes the cc and gcc GNU compilers for compiling C
   code.



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Re-exporting primitive operations of a private type (like "-", and 'min)
  2005-10-31  4:15   ` Anonymous Coward
  2005-10-31  4:34     ` Anonymous Coward
@ 2005-10-31  6:14     ` Jeffrey R. Carter
  2005-11-01  3:39       ` Anonymous Coward
  2005-10-31  8:27     ` Niklas Holsti
  2 siblings, 1 reply; 17+ messages in thread
From: Jeffrey R. Carter @ 2005-10-31  6:14 UTC (permalink / raw)


Anonymous Coward wrote:

>       function Subtract (Left, Right : in Private_Distance_Type)
>         return Private_Distance_Type is
> 
>       begin
> 
>          --Kazakov's suggested approach.  This is good because it's
>          --simple, and doesn't require type conversions.  
>          --(May not work with gnat 3.15p)
> 
>          return (Left - Right);
> 
>       end Subtract;

This isn't going to work. Subtract has to be defined for the private type's 
parent (as a renaming of "-"), so the private type also has Subtract defined. 
Then you can define "-" for the private type as a renaming of Subtract.

Here, "-" refers to the explicitly defined operation, which is a renaming of 
Subtract, so this is infinite recursion.

-- 
Jeff Carter
"There's no messiah here. There's a mess all right, but no messiah."
Monty Python's Life of Brian
84



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Re-exporting primitive operations of a private type (like "-", and 'min)
  2005-10-31  4:15   ` Anonymous Coward
  2005-10-31  4:34     ` Anonymous Coward
  2005-10-31  6:14     ` Jeffrey R. Carter
@ 2005-10-31  8:27     ` Niklas Holsti
  2005-10-31  9:18       ` Dmitry A. Kazakov
  2005-11-02  9:50       ` Jean-Pierre Rosen
  2 siblings, 2 replies; 17+ messages in thread
From: Niklas Holsti @ 2005-10-31  8:27 UTC (permalink / raw)


Anonymous Coward wrote:
>>The whole point of private types is that the only visible operations
>>on them are assignment, equality and inequality, and any explicitly
>>defined operations in the visible part of the package
>>specification. 
> 
> 
> That makes sense.  As a default, it probably would be a poor language
> design to have private types automatically export public primitive
> operations.  If I created an Altitude_Type, I wouldn't want to inherit
> the "+" operation.

The following is perhaps not quite on the original topic, but this 
thread reminds me of an idea for a new feature related to private 
types that I would like to present.

My Ada packages often define types that are *mostly* private in 
the sense that I only want the clients to use a restricted set of 
operations and properties of the type. However, I often do not 
make these types actual private types because I want to reveal 
some properties, such as discreteness, that I cannot now specify 
for a private type.

I would like to be able to reveal some properties of private types 
in the same way as we can now define generic formal types, for 
example saying that the type is discrete (type T is (<>)) or is a 
modular type (type T is mod <>). So I would like to write, for 
example, a package like this:

    package P is

       type Element is private (<>);
       -- This is not Ada. The intended meaning is that type
       -- Element is private, but is a discrete type.

       -- Some operations using Element.

    private

       type Element is (This, That, The_Other);
       -- See, Element is really a discrete type.

    end P;

Other (client) packages can then use the fact that P.Element is a 
discrete type, for example by using P.Element as an index type:

    with P;

    package Client is

       type Set is array (P.Element) of Boolean;
       ...
    end Client;

However, the whole definition of P.Element would still be hidden, 
so clients could not refer for example to P.Element'(P.This).

There would be a pleasing symmetry in this new feature if the 
properties that could be revealed about a private type would match 
exactly the properties that can now be defined for a generic 
formal type. A private type with some properties revealed in this 
way could then be used as the actual type to instantiate a generic 
with a formal type that has matching properties.

There are even some places in the Ada LRM where the proposed 
feature would be useful. For example, the LRM (95) now defines, in 
13.7.1:

    package System.Storage_Elements is
       ...
       type Storage_Offset is range "implementation defined";
       ...
       type Storage_Element is mod "implementation defined";
       ...
    end System.Storage_Elements;

With the new feature, the "implementation defined" pseudocode 
could be replaced by real code:

       type Storage_Offset is private range <>;  -- Not Ada.
       type Storage_Element is private mod <>;   -- Not Ada.

The full type declarations would be in the private part of the 
package, as usual.

In such declarations, the "private" keyword is perhaps 
unnecessary, since the presence of the box "<>" shows that the 
declared type is partly hidden.

Does this idea appeal to anyone?

-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
       .      @       .



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Re-exporting primitive operations of a private type (like "-", and 'min)
  2005-10-31  8:27     ` Niklas Holsti
@ 2005-10-31  9:18       ` Dmitry A. Kazakov
  2005-11-02  9:50       ` Jean-Pierre Rosen
  1 sibling, 0 replies; 17+ messages in thread
From: Dmitry A. Kazakov @ 2005-10-31  9:18 UTC (permalink / raw)


On Mon, 31 Oct 2005 10:27:51 +0200, Niklas Holsti wrote:

> Anonymous Coward wrote:
>>>The whole point of private types is that the only visible operations
>>>on them are assignment, equality and inequality, and any explicitly
>>>defined operations in the visible part of the package
>>>specification. 
>> 
>> That makes sense.  As a default, it probably would be a poor language
>> design to have private types automatically export public primitive
>> operations.  If I created an Altitude_Type, I wouldn't want to inherit
>> the "+" operation.
> 
> The following is perhaps not quite on the original topic, but this 
> thread reminds me of an idea for a new feature related to private 
> types that I would like to present.
> 
> My Ada packages often define types that are *mostly* private in 
> the sense that I only want the clients to use a restricted set of 
> operations and properties of the type. However, I often do not 
> make these types actual private types because I want to reveal 
> some properties, such as discreteness, that I cannot now specify 
> for a private type.
> 
> I would like to be able to reveal some properties of private types 
> in the same way as we can now define generic formal types, for 
> example saying that the type is discrete (type T is (<>)) or is a 
> modular type (type T is mod <>).

[...]

> Does this idea appeal to anyone?

That would a repetition of the error made with generics. Instead of

   type Element is private (<>);

it should be just

   type Element is new Abstract_Integer with private;

which would solve everything.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Re-exporting primitive operations of a private type (like "-", and 'min)
  2005-10-31  6:14     ` Jeffrey R. Carter
@ 2005-11-01  3:39       ` Anonymous Coward
  2005-11-01  4:47         ` Jeffrey R. Carter
  2005-11-01 14:11         ` Robert A Duff
  0 siblings, 2 replies; 17+ messages in thread
From: Anonymous Coward @ 2005-11-01  3:39 UTC (permalink / raw)


In article <iDi9f.3949$yX2.741@newsread2.news.pas.earthlink.net>, Jeffrey R. Carter wrote:
> Anonymous Coward wrote:
> 
>>       function Subtract (Left, Right : in Private_Distance_Type)
>>         return Private_Distance_Type is
>> 
>>       begin
>> 
>>          --Kazakov's suggested approach.  This is good because it's
>>          --simple, and doesn't require type conversions.  
>>          --(May not work with gnat 3.15p)
>> 
>>          return (Left - Right);
>> 
>>       end Subtract;
> 
> This isn't going to work. Subtract has to be defined for the private
> type's parent (as a renaming of "-"), so the private type also has
> Subtract defined.  Then you can define "-" for the private type as a
> renaming of Subtract.
> 
> Here, "-" refers to the explicitly defined operation, which is a
> renaming of Subtract, so this is infinite recursion.

You seem to be correct.  The segmentation fault was probably due to
running out of stack space because of an infinite recursion.  I didn't
suspect that at first, because I didn't get the compiler warning about
infinite recursion this time, so it seems the renaming made put the
flaw beyond gnats detection.

So in the end, the 'base technique doesn't work either, and I'm left
with type conversions that explicitly reference the parent:


    function "-" (Left, Right : in Private_Distance_Type)
      return Private_Distance_Type is

    begin

       return Private_Distance_Type(Public_Distance_Type(Left) - 
                                    Public_Distance_Type(Right));

    end "-";

Did someone say ADA 2005 will handle this better?  When is ADA 2005
expected to roll out?



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Re-exporting primitive operations of a private type (like "-", and 'min)
  2005-11-01  3:39       ` Anonymous Coward
@ 2005-11-01  4:47         ` Jeffrey R. Carter
  2005-11-01 23:43           ` Anonymous Coward
  2005-11-01 14:11         ` Robert A Duff
  1 sibling, 1 reply; 17+ messages in thread
From: Jeffrey R. Carter @ 2005-11-01  4:47 UTC (permalink / raw)


Anonymous Coward wrote:
> 
> So in the end, the 'base technique doesn't work either, and I'm left
> with type conversions that explicitly reference the parent:

You should be able to say (in the private part)

function Subtract (Left, Right : in Public_Distance_Type)
return Public_Distance_Type renames "-";

type Private_Distance_Type is new Public_Distance_Type;
-- Subtract is defined for Private_Distance_Type.

function "-" (Left, Right : in Private_Distance_Type)
return Private_Distance_Type renames Subtract;

-- 
Jeff Carter
"Son of a window-dresser."
Monty Python & the Holy Grail
12



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Re-exporting primitive operations of a private type (like "-", and 'min)
  2005-11-01  3:39       ` Anonymous Coward
  2005-11-01  4:47         ` Jeffrey R. Carter
@ 2005-11-01 14:11         ` Robert A Duff
  1 sibling, 0 replies; 17+ messages in thread
From: Robert A Duff @ 2005-11-01 14:11 UTC (permalink / raw)


Anonymous Coward <bogus_addy@bogus_domain.net> writes:

> You seem to be correct.  The segmentation fault was probably due to
> running out of stack space because of an infinite recursion.

Yes.  Some compilers do not have stack checking turned on by default.
If not, there is an option to turn it on, in which case infinite
recursion will raise Storage_Error, which might be easier to debug.

- Bob



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Re-exporting primitive operations of a private type (like "-", and 'min)
  2005-11-01  4:47         ` Jeffrey R. Carter
@ 2005-11-01 23:43           ` Anonymous Coward
  2005-11-02  3:35             ` Jeffrey R. Carter
  0 siblings, 1 reply; 17+ messages in thread
From: Anonymous Coward @ 2005-11-01 23:43 UTC (permalink / raw)


In article <ErC9f.4432$yX2.1697@newsread2.news.pas.earthlink.net>, Jeffrey R. Carter wrote:
> 
> You should be able to say (in the private part)
> 
> function Subtract (Left, Right : in Public_Distance_Type)
> return Public_Distance_Type renames "-";
> 
> type Private_Distance_Type is new Public_Distance_Type;
> -- Subtract is defined for Private_Distance_Type.
> 
> function "-" (Left, Right : in Private_Distance_Type)
> return Private_Distance_Type renames Subtract;

That would probably work as long as the definition of Subtract does a
type conversion explicitly on the Left and Right to the parent types.
But what are the advantages?  Why would I define a Subtract operation
and use a renames clause, when I can simply define a "-" operation
directly?  

The "-" operation must still be replaced, and it still has to have a
declaration in the public part.  So in your case above, there would
have to be a 

  function "-" (Left, Right : in Private_Distance_Type)
    return Private_Distance_Type; 

in the public part.



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Re-exporting primitive operations of a private type (like "-", and 'min)
  2005-11-01 23:43           ` Anonymous Coward
@ 2005-11-02  3:35             ` Jeffrey R. Carter
  0 siblings, 0 replies; 17+ messages in thread
From: Jeffrey R. Carter @ 2005-11-02  3:35 UTC (permalink / raw)


Anonymous Coward wrote:

> That would probably work as long as the definition of Subtract does a
> type conversion explicitly on the Left and Right to the parent types.
> But what are the advantages?  Why would I define a Subtract operation
> and use a renames clause, when I can simply define a "-" operation
> directly?  

No. Subtract is defined for the parent type as a renaming of "-". Thus, calling 
Subtract is the same as calling "-".

The private type derives from the parent type after the declaration of Subtract, 
so it also has Subtract defined as a renaming of the predefined "-". It also has 
a redefined "-" that must be explicitly defined. The redefined "-" is then 
defined as a renaming of Subtract, so calling the redefined "-" is the same as 
calling Subtract, and calling Subtract is the same as calling the predefined "-".

That's kind of a mouthful, but it means the explicitly defined "-" for the 
private type is actually the predefined "-".

The advantage of this approach is that "-" remains the predefined operation for 
the type. It may also be a little shorter and easier to get right.

> The "-" operation must still be replaced, and it still has to have a
> declaration in the public part.  So in your case above, there would
> have to be a 
> 
>   function "-" (Left, Right : in Private_Distance_Type)
>     return Private_Distance_Type; 
> 
> in the public part.

Certainly. That's the only reason you'd go through all this.

-- 
Jeff Carter
"In the frozen land of Nador they were forced to
eat Robin's minstrels, and there was much rejoicing."
Monty Python & the Holy Grail
70



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Re-exporting primitive operations of a private type (like "-", and 'min)
  2005-10-31  8:27     ` Niklas Holsti
  2005-10-31  9:18       ` Dmitry A. Kazakov
@ 2005-11-02  9:50       ` Jean-Pierre Rosen
  2005-11-03  9:15         ` Niklas Holsti
  1 sibling, 1 reply; 17+ messages in thread
From: Jean-Pierre Rosen @ 2005-11-02  9:50 UTC (permalink / raw)


Niklas Holsti a �crit :
> With the new feature, the "implementation defined" pseudocode could be 
> replaced by real code:
> 
>       type Storage_Offset is private range <>;  -- Not Ada.
>       type Storage_Element is private mod <>;   -- Not Ada.
> 
> The full type declarations would be in the private part of the package, 
> as usual.
> 
> In such declarations, the "private" keyword is perhaps unnecessary, 
> since the presence of the box "<>" shows that the declared type is 
> partly hidden.
> 
> Does this idea appeal to anyone?
> 
I fail to see the benefit. The only thing that would be "hidden" with 
such a declaration is the actual value of the bounds. But you could get 
them with 'First and 'Last. So, there would be no benefit in pretending 
that they are "private".

-- 
---------------------------------------------------------
            J-P. Rosen (rosen@adalog.fr)
Visit Adalog's web site at http://www.adalog.fr



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Re-exporting primitive operations of a private type (like "-", and 'min)
  2005-11-02  9:50       ` Jean-Pierre Rosen
@ 2005-11-03  9:15         ` Niklas Holsti
  0 siblings, 0 replies; 17+ messages in thread
From: Niklas Holsti @ 2005-11-03  9:15 UTC (permalink / raw)


Jean-Pierre Rosen wrote:
> Niklas Holsti a �crit :
> 
>> With the new feature, the "implementation defined" pseudocode could be 
>> replaced by real code:
>>
>>       type Storage_Offset is private range <>;  -- Not Ada.
>>       type Storage_Element is private mod <>;   -- Not Ada.
>>
>> The full type declarations would be in the private part of the 
>> package, as usual.
>>
>> In such declarations, the "private" keyword is perhaps unnecessary, 
>> since the presence of the box "<>" shows that the declared type is 
>> partly hidden.
>>
>> Does this idea appeal to anyone?
>>
> I fail to see the benefit. The only thing that would be "hidden" with 
> such a declaration is the actual value of the bounds. But you could get 
> them with 'First and 'Last. So, there would be no benefit in pretending 
> that they are "private".

I think there would be a benefit -- it would *force* the clients 
of this package to use 'First and 'Last, instead of other *not 
standardized* items, for example some named numbers that may be 
defined in a particular implementation of this package.

But I agree that the advantage in this example is small. Let me 
explain the context more clearly.

You have an Ada program that contains a package A which defines a 
type A.T, and a package B that uses A.T in some way. For some 
reason (say, different platforms or different product variants) 
you have several variants of package A, say A', A" and so on. They 
all have the Ada name A, but they exist in different source 
directories, for example. To build a particular version of this 
program, you select a variant of A and compile it together with B. 
The variants define the type A.T in different ways; A' may define 
it as an enumeration, A" as an integer type, etc.

You want the same package B to be compatible with all variants of 
package A, even though the different variants of type A.T differ 
in detail. Thus, there must be some form of contract or 
specification that every variant of type A.T must satisfy and 
which defines how package B can use type A.T.

The only way to express such a contract in Ada, now, is to define 
A.T as (fully) private and provide the necessary operations in 
package A. But this means that A.T cannot be (visibly) discrete, 
so it cannot be used as an array index, cannot be used as a 
discriminant, and cannot be an actual type in generic 
instantiations where the formal type is more specific than "private".

An alternative would be to make package B generic, with a generic 
formal type standing for A.T, and then instantiate B with whatever 
variant of A.T is at hand. The definition of the generic 
parameters of B then define the contract. However, this method is 
not very practical when there are many packages (B, C, D, ... ZZ) 
that depend on A.T, and perhaps on other packages with variants. 
Moreover, it seems like overkill when you know that there will be 
only a single instantiation of B (and C, D, ... ZZ) in any version 
of the program.

The contract aspect of Ada generics is a good thing, but it is 
one-sided: it only lets the generic unit specify what it *expects* 
of a type that it will be given; there is now no similar way to 
specify what a unit *promises* of a type that it *provides*. One 
can only define a public type, which usually overspecifies the 
contract, or a (fully) private type, which has limitations as I 
said above.

My proposal aims for a similar contract aspect for private types, 
to let the provider of a type specify the type's properties 
without forcing "the rest of the world" to be defined as generic 
and parametrized with this type.

-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
       .      @       .



^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2005-11-03  9:15 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-10-29 21:19 Re-exporting primitive operations of a private type (like "-", and 'min) Anonymous Coward
2005-10-30  8:57 ` Dmitry A. Kazakov
2005-10-30  9:18 ` Jeffrey R. Carter
2005-10-30 14:16   ` Martin Krischik
2005-10-30 22:35     ` Robert A Duff
2005-10-31  4:15   ` Anonymous Coward
2005-10-31  4:34     ` Anonymous Coward
2005-10-31  6:14     ` Jeffrey R. Carter
2005-11-01  3:39       ` Anonymous Coward
2005-11-01  4:47         ` Jeffrey R. Carter
2005-11-01 23:43           ` Anonymous Coward
2005-11-02  3:35             ` Jeffrey R. Carter
2005-11-01 14:11         ` Robert A Duff
2005-10-31  8:27     ` Niklas Holsti
2005-10-31  9:18       ` Dmitry A. Kazakov
2005-11-02  9:50       ` Jean-Pierre Rosen
2005-11-03  9:15         ` Niklas Holsti

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox