comp.lang.ada
 help / color / mirror / Atom feed
* Re: Can't export object of private type
       [not found] <F7JoCB.JxB@syd.csa.com.au>
@ 1999-02-24  0:00 ` Don Harrison
  1999-02-24  0:00   ` Tom Moran
                     ` (2 more replies)
  0 siblings, 3 replies; 128+ messages in thread
From: Don Harrison @ 1999-02-24  0:00 UTC (permalink / raw)


Looks like everyone's a bit coy on this question. :)


The best workaround I've been able to come up with is to export an access 
variable to the singleton. For example,

  package Singleton is

    type Singleton_Type is tagged private;
    type Access_Singleton_Type is access all Singleton_Type'Class;

    procedure Do_Something (S: in Singleton_Type);

    S_Ptr: Access_Singleton_Type;

  private
    type Singleton_Type is tagged null record;
    S: aliased Singleton_Type;
  end;

initialising the access variable at elaboration ..

  S_Ptr := S.all'Access;

and using it in clients ..

  Do_Something (S_Ptr.all);



Any better suggestions? ..


(Of course, it would be easier if Ada just allowed you to export a variable 
of a private type from the same package. :)  Oh, well.



-- 
Don (Harrison).   donh at syd.csa.com.au






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

* Re: Can't export object of private type
  1999-02-24  0:00 ` Can't export object of private type Don Harrison
  1999-02-24  0:00   ` Tom Moran
@ 1999-02-24  0:00   ` Samuel Mize
  1999-02-24  0:00     ` Tucker Taft
                       ` (2 more replies)
  1999-02-28  0:00   ` Matthew Heaney
  2 siblings, 3 replies; 128+ messages in thread
From: Samuel Mize @ 1999-02-24  0:00 UTC (permalink / raw)


Don Harrison <nospam@thanks.com.au> wrote:
> Looks like everyone's a bit coy on this question. :)

Well, I didn't see any previous message, but maybe that's just me
or my newsreader.

You appear to want to export a variable of a private type, in the
public part of the package that defines that type.

The catch is that the full type definition must be available to the
compiler (if not visible to the user) when a variable is declared, so
it knows how much space to allocate.

At the end of this message I show a workaround using a contained
package.  It ain't pretty, but it compiles.  Note that the private part
of the inner package is NOT visible to the rest of the outer package, so
you should put any subprograms into the inner package.  You can rename
the elements of the inner package for the convenience of the end user.
Of course, that user could also "use" the inner package.

I didn't see anything important in the use of "tagged" for this question,
so I left it out.  Also, I wanted the package name to be meaningful.

> The best workaround I've been able to come up with is to export an access 
> variable to the singleton. For example,

Let me improve your access-based solution.  Changes are in all-caps:

>   package Singleton is
> 
>     type Singleton_Type is tagged private;
>     type Access_Singleton_Type is access all Singleton_Type'Class;
> 
>     procedure Do_Something (S: in Singleton_Type);
> 
>     S_Ptr: CONSTANT Access_Singleton_Type;
> 
>   private
>     type Singleton_Type is tagged null record;
>     S: aliased Singleton_Type;
      S_PTR: CONSTANT ACCESS_SINGLETON_TYPE := S'ACCESS;
>   end;

This way, users of the package don't have to wait for the elaboration
of Singleton's BODY for S_Ptr to denote S -- it does so once the SPEC
has been elaborated.  (E.g, a package spec that "withs" Singleton could
do something meaningful with it.)  (It would be smart to initialize S.)

Also, malicious or careless users can't assign a new value to S_Ptr,
for instance one denoting a procedure's local variable:

   with Singleton;
   procedure Mess_Everybody_Up is
      S: Singleton_Type;
   begin
      S_Ptr := S'Unchecked_Access; -- can't do it with S_Ptr constant!
   end Mess_Everybody_Up;

Best,
Sam Mize

- - - - - -
package Meaningful is

   package Inner is

      type The_Type is private;

      procedure The_Procedure (Param: The_Type);

      An_Instance_Initial_Value: constant The_Type;

   private
      type The_Type is new integer;
      An_Instance_Initial_Value: constant The_Type := 1;
   end Inner;

   --------------
   -- RENAMING DECLARATIONS FOR END-USER VISIBILITY
   --------------

   subtype The_Type is Inner.The_Type;

   procedure The_Procedure (Param: The_Type)
      renames Inner.The_Procedure;

   --------------
   -- HERE FINALLY IS YOUR EXPORTED PRIVATE VARIABLE OBJECT
   --------------
   An_Instance: The_Type := Inner.An_Instance_Initial_Value;

end Meaningful;


-- 
Samuel Mize -- smize@imagin.net (home email) -- Team Ada
Fight Spam: see http://www.cauce.org/ \\\ Smert Spamonam




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

* Re: Can't export object of private type
  1999-02-24  0:00 ` Can't export object of private type Don Harrison
@ 1999-02-24  0:00   ` Tom Moran
  1999-02-24  0:00   ` Samuel Mize
  1999-02-28  0:00   ` Matthew Heaney
  2 siblings, 0 replies; 128+ messages in thread
From: Tom Moran @ 1999-02-24  0:00 UTC (permalink / raw)


What was the original question?  I can't seem to find it.




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

* Re: Can't export object of private type
  1999-02-24  0:00   ` Samuel Mize
@ 1999-02-24  0:00     ` Tucker Taft
  1999-02-25  0:00     ` Don Harrison
  1999-02-28  0:00     ` Matthew Heaney
  2 siblings, 0 replies; 128+ messages in thread
From: Tucker Taft @ 1999-02-24  0:00 UTC (permalink / raw)


Samuel Mize (smize@imagin.net) wrote:
: ...
: You appear to want to export a variable of a private type, in the
: public part of the package that defines that type....

One reasonably nice work-around is to put the variable into
a child package.

: Sam Mize
--
-Tucker Taft   stt@averstar.com   http://www.averstar.com/~stt/
Technical Director, Distributed IT Solutions  (www.averstar.com/tools)
AverStar (formerly Intermetrics, Inc.)   Burlington, MA  USA




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

* Re: Can't export object of private type
  1999-02-24  0:00   ` Samuel Mize
  1999-02-24  0:00     ` Tucker Taft
@ 1999-02-25  0:00     ` Don Harrison
  1999-02-25  0:00       ` Samuel Mize
                         ` (4 more replies)
  1999-02-28  0:00     ` Matthew Heaney
  2 siblings, 5 replies; 128+ messages in thread
From: Don Harrison @ 1999-02-25  0:00 UTC (permalink / raw)


Sam Mize wrote:

:Well, I didn't see any previous message, but maybe that's just me
:or my newsreader.

Looks like you weren't the only one. Here it is again:

----------------------

:Ada doean't allow you to declare a private type and declare an object of that 
:type in the visible part of the same spec. For example, the following is 
:illegal:
:
:  package Private_Stuff is
:    type Private_Type is tagged private;
:    procedure Do_Something (A: in Private_Type);
:    P: Private_Type;
:  private
:    type Private_Type is tagged null record;
:  end;
:
:GNAT protests:
:
:  private_stuff.ads:4:03: error: premature usage of incomplete private type   
:  "Private_Type" defined at line 2
:
:I'm basically trying to implement singletons so that they can be used 
:polymorphically in the same way as other objects - for example
:
:  Do_Something (P);
:
:rather than 
:
:  Private_Stuff.Do_Something;
:
:(Otherwise, I would shove the declaration of P into the body and remove A
:from the signature).
:
:
:Any suggestions?

----------------------


:You appear to want to export a variable of a private type, in the
:public part of the package that defines that type.

Correct. 

Actually, I don't necessarily want to do that. What I'm really after 
is polymorphic singletons - objects that

  1) Have only one instance
  2) Are polymorphic
  3) Are visible to clients
  4) Can be called without a package prefix.

I can acheive two or three, but not all four. :(

:The catch is that the full type definition must be available to the
:compiler (if not visible to the user) when a variable is declared, so
:it knows how much space to allocate.

Yes, Ada doesn't expect its compilers to look ahead.

:At the end of this message I show a workaround using a contained
:package.  It ain't pretty, ...  

If possible, I would prefer something simpler.

:I didn't see anything important in the use of "tagged" for this question,
:so I left it out.  

I want the type to be polymorphic. Otherwise I would just gain the singleton
effect through a (non-generic) package and call their operations differently 
from non-singletons.


:Let me improve your access-based solution.  Changes are in all-caps:
:
:>   package Singleton is
:> 
:>     type Singleton_Type is tagged private;
:>     type Access_Singleton_Type is access all Singleton_Type'Class;
:> 
:>     procedure Do_Something (S: in Singleton_Type);
:> 
:>     S_Ptr: CONSTANT Access_Singleton_Type;
:> 
:>   private
:>     type Singleton_Type is tagged null record;
:>     S: aliased Singleton_Type;
:      S_PTR: CONSTANT ACCESS_SINGLETON_TYPE := S'ACCESS;
:>   end;
:
:This way, users of the package don't have to wait for the elaboration
:of Singleton's BODY for S_Ptr to denote S -- it does so once the SPEC
:has been elaborated.  (E.g, a package spec that "withs" Singleton could
:do something meaningful with it.)  (It would be smart to initialize S.)

Good idea.



Tucker Taft wrote:

:One reasonably nice work-around is to put the variable into
:a child package.

Unfortunately, I would have to sacrifice 1) above.


-- 
Don (Harrison).   donh at syd.csa.com.au






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

* Re: Can't export object of private type
  1999-02-25  0:00     ` Don Harrison
  1999-02-25  0:00       ` Samuel Mize
  1999-02-25  0:00       ` fraser
@ 1999-02-25  0:00       ` robert_dewar
  1999-02-26  0:00         ` Don Harrison
  1999-02-27  0:00         ` Brian Rogoff
  1999-02-28  0:00       ` Matthew Heaney
  1999-03-01  0:00       ` Tom Moran
  4 siblings, 2 replies; 128+ messages in thread
From: robert_dewar @ 1999-02-25  0:00 UTC (permalink / raw)


In article <F7p7Dq.DE1@syd.csa.com.au>,
  nospam@thanks.com.au wrote:
> :Ada doean't allow you to declare a private type and
> declare an object of that  :type in the visible part of
> the same spec. For example, the following is
> :illegal:
> :
> :  package Private_Stuff is
> :    type Private_Type is tagged private;
> :    procedure Do_Something (A: in Private_Type);
> :    P: Private_Type;
> :  private
> :    type Private_Type is tagged null record;
> :  end;

This is of course wrong at a very fundamental level. The
notion of linear elaboration is central to the integrity
of the Ada design, and is a notion that should be fully
understood and familiar to Ada programmers.

You mention "looking ahead", and it is of course true that
some trivial cases could be handled this way, but this
never works in the general case. Consider for example the
following semantic nonsense (which is of course illegal
as a special case of the general observation you are
making)

     type x is private;
     b : x;
     ...
   private
     type x is array (1 .. b'size) of Integer;

The point here is that this is not some kind of arbitrary
restriction, and it should be like parking in New York
City -- "don't even *think* of doing things which violate
the notion of linear elaboration" :-)

Now my own design preference would have been to avoid the
separate private part, and just put a private keyword on
selected declarations. I think the separation of private
parts, nice as it is in the simple cases, has caused SO
much confusion, and SO much wasted implementors time (it
is a source of lots of implementation difficulty) that it
does not begin to be worth it.


-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    




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

* Re: Can't export object of private type
  1999-02-25  0:00     ` Don Harrison
  1999-02-25  0:00       ` Samuel Mize
@ 1999-02-25  0:00       ` fraser
  1999-02-26  0:00         ` Don Harrison
  1999-02-28  0:00         ` Matthew Heaney
  1999-02-25  0:00       ` robert_dewar
                         ` (2 subsequent siblings)
  4 siblings, 2 replies; 128+ messages in thread
From: fraser @ 1999-02-25  0:00 UTC (permalink / raw)


paene lacrimavi postquam nospam@thanks.com.au scribavit:

>Actually, I don't necessarily want to do that. What I'm really after 
>is polymorphic singletons - objects that
>
>  1) Have only one instance
>  2) Are polymorphic
>  3) Are visible to clients
>  4) Can be called without a package prefix.

What about a parameterless function that returns that type?  The only
down side being that you'd have to override it for each extension.
Or maybe that's not a down side, depending on what you want to do.

package Test is

   type T is tagged private;
   procedure Do_Something (With_T : T);

   function P return T;
    --  function P return T'Class might also be what you want.

private

   type T is tagged null record;

end Test;

>:>   package Singleton is
>:> 
>:>     type Singleton_Type is tagged private;
>:>     type Access_Singleton_Type is access all Singleton_Type'Class;
>:> 
>:>     procedure Do_Something (S: in Singleton_Type);

What about "procedure Do_Something (S : access Singleton_Type)", to
avoid a bunch of S.all's everywhere.

For some reason, and it's probably just me, I see the use of .all as a
sort of failure on my part.  It's probably grows out of that thing
C has where '.' is different to '->', even though there's no earthly
reason why the concepts should be separated.  And even worse, C++ lets
you overload the '->' operator, which is just too evil to contemplate.

I just love the way Ada compilers fill in .all for me.  It's so
helpful, and I feel bad when I write code that prevents it from doing
so.  It's like punishing a puppy because it didn't do the dishes.

Oh, not to mention that the C++ model of overloading changes the
darn calling semantics for certain operators.  I mean, at least in
Ada when you say 'X and then Y' you *know* that Y won't be evaluated
unless X is true.  Overloading means that there's no such guarantee
in C++ for the similar 'X && Y'.

Fraser.
(only ranting because I have to use C at work).




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

* Re: Can't export object of private type
  1999-02-25  0:00     ` Don Harrison
@ 1999-02-25  0:00       ` Samuel Mize
  1999-02-26  0:00         ` Don Harrison
  1999-02-28  0:00         ` Matthew Heaney
  1999-02-25  0:00       ` fraser
                         ` (3 subsequent siblings)
  4 siblings, 2 replies; 128+ messages in thread
From: Samuel Mize @ 1999-02-25  0:00 UTC (permalink / raw)


Don Harrison <nospam@thanks.com.au> wrote:

> Actually, I don't necessarily want to do that. What I'm really after
> is polymorphic singletons - objects that
>
>   1) Have only one instance
>   2) Are polymorphic
>   3) Are visible to clients
>   4) Can be called without a package prefix.
>
> I can acheive two or three, but not all four. :(

I think I follow what you mean here.

By "singleton" and (1) you mean that there can exist only one object
of the type.  But a visible type makes that impossible to ensure, so
the approach you were taking is fatally flawed.  Oh, the humanity.

I would represent each singleton with a package, which gives 1 and 3,
and use programming by extension to get points 2 and 4.  Specifically,
we start with:

  package Root_Singleton is
     type Flag is tagged null record;

     type Parameter_Type is (To_Be_Defined);

     procedure Action
        (Param: Flag;
         Other_Params_As_Needed: Parameter_Type);

     type Any_Singleton is access constant Flag'Class;
     Selected: aliased constant Flag := (null record);
  end Root_Singleton;

Any_Singleton is a type for "flag" variables.  It's access-to-constant
so it can denote Selected'Access.

In this package, Action does nothing.  Perhaps you want it to raise an
exception, since you should never call Action with Root_Singleton.Flag.
Or, perhaps there is a meaningful "root" singleton for your hierarchy;
I'm showing a general case.

Anyway, next we can declare an arbitrary number of singletons:

  with Root_Singleton;
  package Venus is
     type Flag is new Root_Singleton.Flag with null record;

     procedure Action
        (Param: Flag;
         Other_Params_As_Needed: Root_Singleton.Parameter_Type);

     Selected: aliased constant Flag := (null record);
  end Venus;

And so on for your other singletons.

Now, the tagged types are NOT the singletons.  Rather, items of the
tagged types act as flags that let you specify the singleton to which
you are referring.  So, your user code can look like this:

    with Root_Singleton; use Root_Singleton;

    with Singleton_Picker;
      -- this function picks the right singleton for the current action,
      -- and returns Selected'Access from that singleton package

    procedure User is
        Selector: Any_Singleton;
        Params: Root_Singleton.Parameter_Type;
    begin
       loop
          Selector := Singleton_Picker;

          Action (Selector, Params);

       end loop;
    end User;

Of course, if you don't need the return value elsewhere, you can
eliminate "Selector" and just have

   loop
      Action (Singleton_Picker);
   end loop;

Does that accomplish what you wanted?

Let me guess.  I bet "singleton" is a common object-oriented term, and
it's usually considered to be a special case of a class.

In Ada terms, it's just a package encapsulating some code and data.  We
can use Ada 95's programming-by-extension capability to execute the
right procedure, based on a flag value.  This isn't really an
object-oriented concept at all, but many people think polymorphism is
inherently tied up with object orientation.

Did that commentary hit the mark, or did I mis-guess the background of
the question?

Best,
Sam Mize

-- 
Samuel Mize -- smize@imagin.net (home email) -- Team Ada
Fight Spam: see http://www.cauce.org/ \\\ Smert Spamonam




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

* Re: Can't export object of private type
  1999-02-25  0:00       ` fraser
@ 1999-02-26  0:00         ` Don Harrison
       [not found]           ` <7b6nqe$75m$1@remarq.com>
                             ` (3 more replies)
  1999-02-28  0:00         ` Matthew Heaney
  1 sibling, 4 replies; 128+ messages in thread
From: Don Harrison @ 1999-02-26  0:00 UTC (permalink / raw)


Fraser wrote:

:paene lacrimavi postquam nospam@thanks.com.au scribavit:
:
:>Actually, I don't necessarily want to do that. What I'm really after 
:>is polymorphic singletons - objects that
:>
:>  1) Have only one instance
:>  2) Are polymorphic
:>  3) Are visible to clients
:>  4) Can be called without a package prefix.
:
:What about a parameterless function that returns that type?  

This seems closest to what I'm after so far. The possible weaknesses are:
 
  1) Having to prefix them with package names to disambiguate 
     specific derivations:

     .. := T.Solo;
     .. := T.Child.Solo;

    (I'm attempting to avoid package prefixes altogether, but perhaps 
    this is a vain hope).

  2) Having to retain the same function name even though derivations
     require more specific names. Maybe renaming could help here..

:The only
:down side being that you'd have to override it for each extension.
:Or maybe that's not a down side, depending on what you want to do.

Right - I *do* want to override.

[Fraser's example]

:>:>     procedure Do_Something (S: in Singleton_Type);
:
:What about "procedure Do_Something (S : access Singleton_Type)", to
:avoid a bunch of S.all's everywhere.

Good idea.

:I just love the way Ada compilers fill in .all for me.  

Can you give an example?


-- 
Don (Harrison).   donh at syd.csa.com.au






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

* Re: Can't export object of private type
  1999-02-25  0:00       ` robert_dewar
@ 1999-02-26  0:00         ` Don Harrison
  1999-02-26  0:00           ` robert_dewar
  1999-02-27  0:00         ` Brian Rogoff
  1 sibling, 1 reply; 128+ messages in thread
From: Don Harrison @ 1999-02-26  0:00 UTC (permalink / raw)


Robert Dewar wrote:

:In article <F7p7Dq.DE1@syd.csa.com.au>,
:  nospam@thanks.com.au wrote:
:> :Ada doean't allow you to declare a private type and
:> declare an object of that  :type in the visible part of
:> the same spec. For example, the following is
:> :illegal:
:> :
:> :  package Private_Stuff is
:> :    type Private_Type is tagged private;
:> :    procedure Do_Something (A: in Private_Type);
:> :    P: Private_Type;
:> :  private
:> :    type Private_Type is tagged null record;
:> :  end;
:
:This is of course wrong at a very fundamental level. The
:notion of linear elaboration is central to the integrity
:of the Ada design, and is a notion that should be fully
:understood and familiar to Ada programmers.
 
I'm sure you mean that it's wrong that Ada has a linear elaboration 
model ..and I agree. :)

:You mention "looking ahead", and it is of course true that
:some trivial cases could be handled this way, but this
:never works in the general case. ..

[example of recursive declarations]

:The point here is that this is not some kind of arbitrary
:restriction, ..

No, the point here is that recursive declarations don't make 
any sense ..under any elaboration model.

Because *non-recursive* declarations imply a partial ordering,
a valid elaboration sequence can be determined for them, 
irrespective of declaration order.

:Now my own design preference would have been to avoid the
:separate private part, and just put a private keyword on
:selected declarations. 

I think you're right. In fact, this is the approach used for
Eiffel. 


-- 
Don (Harrison).   donh at syd.csa.com.au






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

* Re: Can't export object of private type
  1999-02-25  0:00       ` Samuel Mize
@ 1999-02-26  0:00         ` Don Harrison
  1999-02-27  0:00           ` Nick Roberts
  1999-02-28  0:00         ` Matthew Heaney
  1 sibling, 1 reply; 128+ messages in thread
From: Don Harrison @ 1999-02-26  0:00 UTC (permalink / raw)


Sam Mize wrote:

:Don Harrison <nospam@thanks.com.au> wrote:
:
:> Actually, I don't necessarily want to do that. What I'm really after
:> is polymorphic singletons - objects that
:>
:>   1) Have only one instance
:>   2) Are polymorphic
:>   3) Are visible to clients
:>   4) Can be called without a package prefix.
:>
:> I can acheive two or three, but not all four. :(
:
:I think I follow what you mean here.
:
:By "singleton" and (1) you mean that there can exist only one object
:of the type.  

Yes.

:But a visible type makes that impossible to ensure, so
:the approach you were taking is fatally flawed.  

Correct.

:I would represent each singleton with a package, which gives 1 and 3,
:and use programming by extension to get points 2 and 4.  

[Sam's example]

:Does that accomplish what you wanted?

Not sure. I'm still digesting it. :)

:Let me guess.  I bet "singleton" is a common object-oriented term, and
:it's usually considered to be a special case of a class.

Pretty much. It's where a class has a single instance rather than many.

:In Ada terms, it's just a package encapsulating some code and data.  We
:can use Ada 95's programming-by-extension capability to execute the
:right procedure, based on a flag value.  This isn't really an
:object-oriented concept at all, but many people think polymorphism is
:inherently tied up with object orientation.

It's true there are different kinds of polymorphism. Ada had at least 
two before OO was introduced:

  1) Coercive (Unchecked_Conversion etc.)
  2) Parametric (generics, discriminants).


-- 
Don (Harrison).   donh at syd.csa.com.au






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

* Re: Can't export object of private type
  1999-02-26  0:00         ` Don Harrison
@ 1999-02-26  0:00           ` robert_dewar
  1999-02-26  0:00             ` bourguet
                               ` (3 more replies)
  0 siblings, 4 replies; 128+ messages in thread
From: robert_dewar @ 1999-02-26  0:00 UTC (permalink / raw)


In article <F7r2DF.23y@syd.csa.com.au>,
  nospam@thanks.com.au wrote:
> Because *non-recursive* declarations imply a partial
> ordering, a valid elaboration sequence can be determined
> for them, irrespective of declaration order.

I know that seems reasonable for simple cases, but this
approach simply will not work, it is recursively
undecidable in the general case what ordering should be
used, since it depends on computational paths.

Linear elaboration is a model that enormously simplifies
the semantics of the language, and allows much more
powerful declarational forms (since it allows a general
unification of declarations and computations).

It is really fundamental to the language. The example I
gave was a very simple one, where you can imagine that
somehow it could be statically detected to be "recursive"
(note that you do NOT have a formal definition of what
you mean by recursive here, and you will find that any
attempt to formalize this definition will fail.)

The advantage of private parts is of course the nice
compartmentalization. Indeed we have on the drawing boards
for GNAT a feature to have the private parts in separate
files which will be very handy for target specialization
and indeed for general abstraction.

So that is the argument on the other side, and it is indeed
a powerful one!

But to try to compromise the notion of linear elaboration
in Ada and replace it with a notion of dependencies will
fail miserably.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    




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

* Re: Can't export object of private type
  1999-02-26  0:00           ` robert_dewar
  1999-02-26  0:00             ` bourguet
@ 1999-02-26  0:00             ` dennison
  1999-03-01  0:00             ` Stephen Leake
  1999-03-01  0:00             ` Don Harrison
  3 siblings, 0 replies; 128+ messages in thread
From: dennison @ 1999-02-26  0:00 UTC (permalink / raw)


In article <7b5u87$s88$1@nnrp1.dejanews.com>,
  robert_dewar@my-dejanews.com wrote:
> compartmentalization. Indeed we have on the drawing boards
> for GNAT a feature to have the private parts in separate
> files which will be very handy for target specialization
> and indeed for general abstraction.

An intriguing idea. Will this separation be required, or just allowed?

T.E.D.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    




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

* Re: Can't export object of private type
  1999-02-26  0:00           ` robert_dewar
@ 1999-02-26  0:00             ` bourguet
  1999-02-26  0:00               ` Samuel T. Harris
  1999-02-28  0:00               ` dewar
  1999-02-26  0:00             ` dennison
                               ` (2 subsequent siblings)
  3 siblings, 2 replies; 128+ messages in thread
From: bourguet @ 1999-02-26  0:00 UTC (permalink / raw)


In article <7b5u87$s88$1@nnrp1.dejanews.com>,
  robert_dewar@my-dejanews.com wrote:
...
> The advantage of private parts is of course the nice
> compartmentalization. Indeed we have on the drawing boards
> for GNAT a feature to have the private parts in separate
> files which will be very handy for target specialization
> and indeed for general abstraction.
...

Well, this is a feature I'd like, especially if the compilation of
a unit "withing" the package can be compiled (and code generated)
without the private part. More or less like inter package inline
is currently handled by gnat: you have a performance gain if you accept
the dependancy but you may prefer the flexibility of the independancy...
well I'd even accept that all the program have to be compiled with the
same mode.

-- Jean-Marc

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    




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

* Re: Can't export object of private type
  1999-02-26  0:00         ` Don Harrison
       [not found]           ` <7b6nqe$75m$1@remarq.com>
  1999-02-26  0:00           ` fraser
@ 1999-02-26  0:00           ` Samuel Mize
  1999-03-01  0:00             ` Don Harrison
  1999-02-28  0:00           ` Matthew Heaney
  3 siblings, 1 reply; 128+ messages in thread
From: Samuel Mize @ 1999-02-26  0:00 UTC (permalink / raw)


Don Harrison <nospam@thanks.com.au> wrote:
a lot, with the following side issue at the end:

> :I just love the way Ada compilers fill in .all for me.  
> 
> Can you give an example?

Sure.  If the access value denotes a record value, you don't have
to put ".all" to access the record's fields:

    F := Access_Value.all.Field;
    F := Access_Value.Field;

This requires different syntax in C ("@" and "." versus "->", IIRC).
In a case like this, it's unlikely you are making a mistake, so Ada
assumes you want the implicit ".all".

On the other hand, mis-using a pointer to a scalar is a common
error, so Ada doesn't infer any de-references -- you have to do
them manually.

Best,
Sam Mize

-- 
Samuel Mize -- smize@imagin.net (home email) -- Team Ada
Fight Spam: see http://www.cauce.org/ \\\ Smert Spamonam




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

* Re: Can't export object of private type
  1999-02-26  0:00             ` bourguet
@ 1999-02-26  0:00               ` Samuel T. Harris
  1999-02-27  0:00                 ` Jean-Pierre Rosen
  1999-02-27  0:00                 ` Simon Wright
  1999-02-28  0:00               ` dewar
  1 sibling, 2 replies; 128+ messages in thread
From: Samuel T. Harris @ 1999-02-26  0:00 UTC (permalink / raw)


bourguet@my-dejanews.com wrote:
> 
> In article <7b5u87$s88$1@nnrp1.dejanews.com>,
>   robert_dewar@my-dejanews.com wrote:
> ...
> > The advantage of private parts is of course the nice
> > compartmentalization. Indeed we have on the drawing boards
> > for GNAT a feature to have the private parts in separate
> > files which will be very handy for target specialization
> > and indeed for general abstraction.
> ...
> 
> Well, this is a feature I'd like, especially if the compilation of
> a unit "withing" the package can be compiled (and code generated)
> without the private part. More or less like inter package inline
> is currently handled by gnat: you have a performance gain if you accept
> the dependancy but you may prefer the flexibility of the independancy...
> well I'd even accept that all the program have to be compiled with the
> same mode.
> 
> -- Jean-Marc

I can say from experience with the old Rational R1000 that
such a facility is very powerful in dealing with variant code,
especially code which varies because of target architectures
to be supported.

While the R1000 did not allow putting the private part in
a separate file as, I believe, Robert is proposing, its
delination of spec views and code views kept the private
part in the code view (or at least that was the perceived
affect). Thus changes to the private part of a package
never caused a compilation hit on dependent units.

Using private or limited types is clearly advantageous
from a design level because dependent units have no
visibility to the private type declaration. However,
classical Ada compilers still have a compilation
dependency. One can work around this by defining the
private type as an access type to an incomplete type
definition in the private part. In this case, one is
allowed to complete the accessed type in the package
body. While this eliminates the compilation dependency,
it introduces a (sometimes unwanted) pointer.

This construction allows one to hide all the variant
details in the package body thus providing a single
specification for all variations. This is a very
important goal.

Allowing the private part in a separate also file gives
me the best of both. I avoid the recompilation hit and
I don't have to use access types if I don't want to.
I expect gnatchop will have an option to take existing
source and split out the private part as appropriate.
The reverse opertion will also be needed.
Will the default file extension be xxx.adp?

-- 
Samuel T. Harris, Principal Engineer
Raytheon, Scientific and Technical Systems
"If you can make it, We can fake it!"




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

* Re: Can't export object of private type
  1999-02-26  0:00         ` Don Harrison
       [not found]           ` <7b6nqe$75m$1@remarq.com>
@ 1999-02-26  0:00           ` fraser
  1999-03-01  0:00             ` Don Harrison
  1999-02-26  0:00           ` Samuel Mize
  1999-02-28  0:00           ` Matthew Heaney
  3 siblings, 1 reply; 128+ messages in thread
From: fraser @ 1999-02-26  0:00 UTC (permalink / raw)


I nearly cried when nospam@thanks.com.au said:


>:I just love the way Ada compilers fill in .all for me.  

>Can you give an example?

Sure.  This is an idiom I use all the time (well, until I wrote a generic dynamic
array package, but that's another story):

   type Array_Type is array (Positive range <>) of Integer;
   type Array_Access is access Array_Type;

   X : Array_Access;
   Y : Integer;
   Z : Array_Type (1 .. Size);
begin

   X := new Array_Type'(1 .. Size);

   Y := X (3);     --  same as X.all (3)

   Z := X.all;     --  .all required here
end;

Subprogram access types are similar.  Bertrand Meyer goes into this sort of thing
in his Eiffel book, but I can't remember the term he used.  You know, the bit
about everything being accessed the same way, regardless of the underlying type.
I think Eiffel (at least in its first incarnation, I haven't checked the language's
revision history) goes a little overboard in its race for purity (but that's another
article).  Not having to worry about whether something's an array or an array access
when you index it is a small plus, but it's representative of a wider philosopher.

Fraser.




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

* Re: Can't export object of private type
       [not found]           ` <7b6nqe$75m$1@remarq.com>
@ 1999-02-26  0:00             ` fraser
  1999-02-27  0:00               ` Nick Roberts
  0 siblings, 1 reply; 128+ messages in thread
From: fraser @ 1999-02-26  0:00 UTC (permalink / raw)


I nearly cried when fraser@synopsys.throw.this.bit.away.com said:

> ... but it's representative of a wider philosopher.

Um, I wasn't really talking about great thinkers who spend too much of
their time in concurrency abstractions.  Obviously, that word should
have been philosophy.  Sorry.

Fraser.




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

* Re: Can't export object of private type
  1999-02-26  0:00               ` Samuel T. Harris
@ 1999-02-27  0:00                 ` Jean-Pierre Rosen
  1999-02-27  0:00                 ` Simon Wright
  1 sibling, 0 replies; 128+ messages in thread
From: Jean-Pierre Rosen @ 1999-02-27  0:00 UTC (permalink / raw)


While we're fancying on separating private parts, what about this:

package Pack is
   ...
private is separate;
end Pack;

Then:

with Another_Package;
package Pack.private is
   -- here is the separate private part
end Pack;

Gnat would put this in a file called pack.adp ...
(well, I just discovered this one was allready taken. Let's call it
.adj (for Junk), since it's RBKD favorite's word in private ;-)

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







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

* Re: Can't export object of private type
  1999-02-25  0:00       ` robert_dewar
  1999-02-26  0:00         ` Don Harrison
@ 1999-02-27  0:00         ` Brian Rogoff
  1999-03-01  0:00           ` robert_dewar
  1 sibling, 1 reply; 128+ messages in thread
From: Brian Rogoff @ 1999-02-27  0:00 UTC (permalink / raw)


On Thu, 25 Feb 1999 robert_dewar@my-dejanews.com wrote:
> ... snip ...
> 
> Now my own design preference would have been to avoid the
> separate private part, and just put a private keyword on
> selected declarations. 

I suppose that would be equivalent to an upwardly compatible 
extension of Ada which allowed interleaving of public and private 
sections, like C++. Yes, I know, this has been discussed before on 
c.l.a., there is nothing new under the sun, etc., etc. ad nauseum :-) 
Looking forward to Ada 200X...

-- Brian





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

* Re: Can't export object of private type
  1999-02-26  0:00               ` Samuel T. Harris
  1999-02-27  0:00                 ` Jean-Pierre Rosen
@ 1999-02-27  0:00                 ` Simon Wright
  1 sibling, 0 replies; 128+ messages in thread
From: Simon Wright @ 1999-02-27  0:00 UTC (permalink / raw)


"Samuel T. Harris" <sam_harris@hso.link.com> writes:

> Will the default file extension be xxx.adp?

In 3.11, .adp is the extension for Project files.




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

* Re: Can't export object of private type
  1999-02-26  0:00         ` Don Harrison
@ 1999-02-27  0:00           ` Nick Roberts
  1999-03-01  0:00             ` Don Harrison
  1999-03-01  0:00             ` Don Harrison
  0 siblings, 2 replies; 128+ messages in thread
From: Nick Roberts @ 1999-02-27  0:00 UTC (permalink / raw)


I think possibly you guys are trying to use a sledgehammer to crack a nut
here.

One possible solution is: (a) provide a base (or common) package, which
defines a selector type; (b) implement each singleton as a (child) package;
(c) provide a 'gateway' package which provides dynamic selection of the
singletons.

E.g. (choosing the child package option):

   package Planetary is
      type Distance is digits 6 range 0.0 .. 1.0e14; -- metres
      type Time is ...;
      ...
      type Planet_Id is private;
      Planet_Error: exception;
   private
      type Planet_Id is new Positive range 1..99;
      ...
   end Planetary;

   package Planetary.Mercury is
      function Equatorial_Diameter return Distance;
      function Solar_Distance (T: in Time) return Distance;
      ...
      Id: constant Planet_Id;
   private
      ...
      Id: constant Planet_Id := 1;
   end Planetary.Mercury;

   ... etc. for the other planets, numbered 2, 3, etc.

   package Planetary.General_Planet is
      function Equatorial_Diameter (Planet: in Planet_Id) return Distance;
      function Solar_Distance (Planet: in Planet_Id; T: in Time) return
Distance;
      ...
   end Planetary.General_Planet;

The bodies of the functions in General_Planet contain a 'case' statement
which selects the appropriate function of the appropriate package to call:

      function Equatorial_Diameter (Planet: in Planet_Id) return Distance is
      begin
         case Planet is
            when Mercury.Id => return Mercury.Equatorial_Distance;
            ...
            when others => raise Planet_Error;
         end case;
      end Equatorial_Diameter;

In reality, the implementation may have to be more sophisticated than this.

To add a new planet, you only have to edit and (re)compile: (a) the new
planet package (spec & body); (b) the General_Planet package body.  Simple!

There will be many variations possible on this theme for each different
specific application, many of them neater than the above.

Another possible scheme that might suit you is: (a) declare a limited tagged
type which is derived from Finalization.Limited_Controlled; (b) implement
Initialize so that it increments a counter (which is itself initialized to
0), and if it goes above 1 (or some other number), raise an exception; (c)
implement Finalize so it decrements the counter.  This way you can
polymorphise the type as normal, but be sure no more than one object of the
type exists at any one time.

One needs to make a distinction between a design concept and the
implementational mechanism of that design concept, and not make the mistake
of thinking that a particular design is inextricably wedded to a particular
mechanism.  It all depends on what you're trying to do (or, rather, why
you're trying to do it).

In all cases: power to your arm (and brain).

-------------------------------------
Nick Roberts
-------------------------------------









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

* Re: Can't export object of private type
  1999-02-26  0:00             ` fraser
@ 1999-02-27  0:00               ` Nick Roberts
  0 siblings, 0 replies; 128+ messages in thread
From: Nick Roberts @ 1999-02-27  0:00 UTC (permalink / raw)


Well I'm a philosopher, and I'm pretty wide :-)
(of the mark, often enough, I know ;-)
--
Nick Roberts







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

* Re: Can't export object of private type
  1999-02-24  0:00 ` Can't export object of private type Don Harrison
  1999-02-24  0:00   ` Tom Moran
  1999-02-24  0:00   ` Samuel Mize
@ 1999-02-28  0:00   ` Matthew Heaney
  2 siblings, 0 replies; 128+ messages in thread
From: Matthew Heaney @ 1999-02-28  0:00 UTC (permalink / raw)


You may want to read what I had to say about singleton patterns in the
patterns archive at the ACM (June 98).

<http://www.acm.org/archives/patterns.html>

If you need a singleton abstraction, then implement it as a state
machine package.

package Singleton is

  procedure Do_Something;

end;

This is the simplest way to implement this idiom.

A singleton is the limiting case of the "well-known" objects pattern,
when the cardinality is one.  For example, you may may know up front
that there are two well-known objects (a "doubleton"?), in which case
you pass an id to each operation:

package Well_Known_Objects is

  type Id_Type is range 1 .. 2;

  procedure Do_Something (Id : in Id_Type);

end Well_Known_Objects;

You can't continue using types, because at some point you bottom-out and
must declare instances of the type, and at the highest levels of
abstraction those objects are going to have to get declared in a state
machine package.

So don't use a type unless you have have a compelling need to.

If you decide that yes, you really want a type, then you'll have to
refer to the singleton object indirectly, because (as you observed) you
can't declare an instance of the type until after the full view of the
type has been declared.

Implement the type as limited and indefinite, and export a function that
returns a pointer to the one object, declared in the body.

package Singletons is

  type Singleton_Type (<>) is limited private;

  procedure Do_Something (Singleton : in out Singleton_Type);

  type Singleton_Access is access all Singleton_Type;

  function Ref return Singleton_Access;

private

  type Singleton_Type is 
    limited record ...;

end Singletons;

package body Singletons is

  Singleton : aliased Singleton_Type;

  function Ref return Singleton_Access is
  begin
    return Singleton'Access;
  end;

...
end Singletons;


Now to use it, you rename the object designated by the pointer:

declare
  Singleton : Singleton_Type renames Ref.all;
begin
...
end;


But like I said, don't use this implementation unless you have a real
compelling need to do so.  Use a state machine package.


nospam@thanks.com.au (Don Harrison) writes:

> The best workaround I've been able to come up with is to export an access 
> variable to the singleton. For example,
> 
>   package Singleton is
> 
>     type Singleton_Type is tagged private;
>     type Access_Singleton_Type is access all Singleton_Type'Class;
> 
>     procedure Do_Something (S: in Singleton_Type);
> 
>     S_Ptr: Access_Singleton_Type;
> 
>   private
>     type Singleton_Type is tagged null record;
>     S: aliased Singleton_Type;
>   end;
> 
> initialising the access variable at elaboration ..
> 
>   S_Ptr := S.all'Access;
> 
> and using it in clients ..
> 
>   Do_Something (S_Ptr.all);
> 
> 
> 
> Any better suggestions? ..
> 
> 
> (Of course, it would be easier if Ada just allowed you to export a variable 
> of a private type from the same package. :)  Oh, well.






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

* Re: Can't export object of private type
  1999-02-24  0:00   ` Samuel Mize
  1999-02-24  0:00     ` Tucker Taft
  1999-02-25  0:00     ` Don Harrison
@ 1999-02-28  0:00     ` Matthew Heaney
  2 siblings, 0 replies; 128+ messages in thread
From: Matthew Heaney @ 1999-02-28  0:00 UTC (permalink / raw)


Samuel Mize <smize@imagin.net> writes:

> > The best workaround I've been able to come up with is to export an access 
> > variable to the singleton. For example,
> 
> Let me improve your access-based solution.  Changes are in all-caps:
> 
> >   package Singleton is
> > 
> >     type Singleton_Type is tagged private;

Better is to declare this type as limited and indefinite:

  type Singleton_Type (<>) is limited private;

This way, no one can declare instances of the type, nor can they assign
another value to the singleton.

I'm not clear why the type needs to be tagged.  Don't make the type
tagged unless you have a compelling reason for doing do.

A better solution is to not use a type at all.  Just implement the
object as a state machine package.

I often see programmers using tagged types everywhere.  Please do not do
this.





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

* Re: Can't export object of private type
  1999-02-25  0:00     ` Don Harrison
                         ` (2 preceding siblings ...)
  1999-02-25  0:00       ` robert_dewar
@ 1999-02-28  0:00       ` Matthew Heaney
  1999-03-01  0:00       ` Tom Moran
  4 siblings, 0 replies; 128+ messages in thread
From: Matthew Heaney @ 1999-02-28  0:00 UTC (permalink / raw)


nospam@thanks.com.au (Don Harrison) writes:

> Actually, I don't necessarily want to do that. What I'm really after 
> is polymorphic singletons - objects that
> 
>   1) Have only one instance
>   2) Are polymorphic
>   3) Are visible to clients
>   4) Can be called without a package prefix.
> 
> I can acheive two or three, but not all four. :(

Hmmm.  So you really do want a polymorphic singleton.  I did just this
in some of my early posts to the patterns archive.  See the stuff about
abstract factories and factory methods:

<http://www.acm.org/archives/patterns.html>

1) If you want one instance, make the type limited and indefinite.  I
explain all this in my posts about singletons, also in the archives.

2) If you want polymorphism, then declare the type as tagged, and refer
   to a class-wide object.

3) Export a function that returns a reference to the object (which is
   declared in the body of the package).

4) Don't use a state machine package, use a type.

package Singletons is

  type Root_Singleton_Type (<>) is abstract tagged limited private;

  <primitive ops for Root_Singleton_Type>

  type Singleton_Access is 
     access all Root_Singleton_Type'Class;  
     -- T'Class, to get dynamic dispatching

  function Ref return Singleton_Access;

private

  type Root_Singleton_Type is abstract tagged limited record...;

end Singletons;

package Singletons.Blue is
  
  type Blue_Singleton_Type is new Root_Singleton with private;

  <override primitive ops>

...
end;


with Singlestons.Blue;
package body Singetons is

  Singleton : aliased Blue_Singleton_Type;

  function Ref return Singleton_Access is
  begin
    return Singleton'Access;
  end;

end Singletons;


You could even choose the specific type of the singleton at run-time;
this is precisely what I did in my abstract factory and factory method
examples.






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

* Re: Can't export object of private type
  1999-02-25  0:00       ` fraser
  1999-02-26  0:00         ` Don Harrison
@ 1999-02-28  0:00         ` Matthew Heaney
  1 sibling, 0 replies; 128+ messages in thread
From: Matthew Heaney @ 1999-02-28  0:00 UTC (permalink / raw)


fraser@synopsys.like.how.smart.are.email.greppers.anyway.com writes:

> What about a parameterless function that returns that type?  The only
> down side being that you'd have to override it for each extension.
> Or maybe that's not a down side, depending on what you want to do.
> 
> package Test is
> 
>    type T is tagged private;
>    procedure Do_Something (With_T : T);
> 
>    function P return T;
>     --  function P return T'Class might also be what you want.
> 
> private
> 
>    type T is tagged null record;
> 
> end Test;


This will only work if you don't have to modify the object.  To do that,
you need to return a reference to the object:

  function Ref return T_Access;

and then say 

    Op (Ref.all);

so refer to the actual object.









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

* Re: Can't export object of private type
  1999-02-26  0:00         ` Don Harrison
                             ` (2 preceding siblings ...)
  1999-02-26  0:00           ` Samuel Mize
@ 1999-02-28  0:00           ` Matthew Heaney
  3 siblings, 0 replies; 128+ messages in thread
From: Matthew Heaney @ 1999-02-28  0:00 UTC (permalink / raw)


nospam@thanks.com.au (Don Harrison) writes:

> :What about a parameterless function that returns that type?  
> 
> This seems closest to what I'm after so far. The possible weaknesses are:
>  
>   1) Having to prefix them with package names to disambiguate 
>      specific derivations:
> 
>      .. := T.Solo;
>      .. := T.Child.Solo;
> 
>     (I'm attempting to avoid package prefixes altogether, but perhaps 
>     this is a vain hope).

No, you don't need package prefixes.  Declare the type as tagged,
limited and indefinite, and have the root-level package export a
function that returns a class-wide object (or a pointer to a class-wide
object), and then you'll dispatch.

Examples of how to do this are in the patterns archive at the ACM.

<http://www.acm.org/archives/patterns.html>

Search for singleton, factory method, abstract factory.  

I was still learning Ada95 at the time I wrote some of that stuff (I've
since improved it), so if anything's unclear, just drop me a note.

Matt




 




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

* Re: Can't export object of private type
  1999-02-25  0:00       ` Samuel Mize
  1999-02-26  0:00         ` Don Harrison
@ 1999-02-28  0:00         ` Matthew Heaney
  1999-03-01  0:00           ` Nick Roberts
  1999-03-01  0:00           ` Samuel Mize
  1 sibling, 2 replies; 128+ messages in thread
From: Matthew Heaney @ 1999-02-28  0:00 UTC (permalink / raw)


Samuel Mize <smize@imagin.net> writes:

> By "singleton" and (1) you mean that there can exist only one object
> of the type.  But a visible type makes that impossible to ensure, so
> the approach you were taking is fatally flawed.  Oh, the humanity.

This is incorrect.  Implement the type as tagged, limited, and
indefinite, which prevents anyone from declaring instances of the type.

The 4 goals listed are all achievable, indeed very simply.

 
> I would represent each singleton with a package, which gives 1 and 3,
> and use programming by extension to get points 2 and 4.  Specifically,
> we start with:

I like the idea of a state machine package, but he wants dynamic
dispatching.  

The way to implement this abstraction is like this:

package P is

  type T (<>) is abstract tagged limited private;

  <primitive ops>

  type T_Access is access all T'Class;

  function Ref return T_Access;

private

  <junk>

end P;


package P.Q is

  type NT is new T with private;

  ...
end;


with P.Q;
package body P is

  O : aliased Q.NT;

  function Ref return T_Access is
  begin
     return O'Access;
  end;

...
end P;



The function Ref, which returns a pointer to an object declared in the
body, is analogous to Eiffel's once functions.







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

* Re: Can't export object of private type
  1999-02-26  0:00             ` bourguet
  1999-02-26  0:00               ` Samuel T. Harris
@ 1999-02-28  0:00               ` dewar
  1999-03-01  0:00                 ` bourguet
  1 sibling, 1 reply; 128+ messages in thread
From: dewar @ 1999-02-28  0:00 UTC (permalink / raw)


In article <7b6f9k$at2$1@nnrp1.dejanews.com>,
  bourguet@my-dejanews.com wrote:
> Well, this is a feature I'd like, especially if the
> compilation of a unit "withing" the package can be
> compiled (and code generated)
> without the private part. More or less like inter package
> inline
> is currently handled by gnat: you have a performance gain
> if you accept
> the dependancy but you may prefer the flexibility of the
> independancy...
> well I'd even accept that all the program have to be
> compiled with the
> same mode.

Interesting idea. Of course you cannot generate code
without the private part present (or at least not in any
reasonably efficient or practical manner). However,
compilation in the RM sense merely requires checking for
semantic correctness, and that can be done without needing
the private part, so that is something interesting to think
about as part of this enhancement (allowing a -gnatc
compilation not to require private parts to be present)

Robert Dewar
Ada Core Technologies

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    




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

* Re: Can't export object of private type
  1999-02-28  0:00         ` Matthew Heaney
  1999-03-01  0:00           ` Nick Roberts
@ 1999-03-01  0:00           ` Samuel Mize
  1 sibling, 0 replies; 128+ messages in thread
From: Samuel Mize @ 1999-03-01  0:00 UTC (permalink / raw)


Matthew Heaney <matthew_heaney@acm.org> wrote:
> Samuel Mize <smize@imagin.net> writes:
> 
>> By "singleton" and (1) you mean that there can exist only one object
>> of the type.  But a visible type makes that impossible to ensure, so
>> the approach you were taking is fatally flawed.  Oh, the humanity.
> 
> This is incorrect.  Implement the type as tagged, limited, and
> indefinite, which prevents anyone from declaring instances of the type.

Good point.  I haven't done enough with abstract types.

>> I would represent each singleton with a package, which gives 1 and 3,
>> and use programming by extension to get points 2 and 4.  Specifically,
>> we start with:
> 
> I like the idea of a state machine package, but he wants dynamic
> dispatching.  

The code I showed did dispatch, based on an identity value -- which was
implemented as a tagged type.  You show another good solution.

In effect, I implemented the singleton as a state-machine package,
with a tagged "identity" or "flag" type for dispatching to the right
package.  The data is hidden inside the package body.

You're implementing it as a regular dispatching type, but you're
using the abstract type mechanism to ensure that nobody else can
declare an instance.

Your approach extends better to "n-tons."

On the other hand, mine may make for clearer code inside the
singleton packages, since you don't have to refer to everything via
the operation's access parameter.

Mine had the very moderate advantage that you only need to wait for
elaboration of the package spec in order to get at the identity of
the singleton (i.e., if a user package calls P.Q.Ref in its spec, it
has to use an elaboration pragma to ensure that P.Q's body has been
elaborated first.

Of course, your approach is a better conceptual match to a development
environment that's heavily using object-oriented methods.

Looks to me as if they're both worth keeping in the back pocket. :-)

Best,
Sam Mize

-- 
Samuel Mize -- smize@imagin.net (home email) -- Team Ada
Fight Spam: see http://www.cauce.org/ \\\ Smert Spamonam




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

* Re: Can't export object of private type
  1999-03-01  0:00           ` Nick Roberts
  1999-03-01  0:00             ` Matthew Heaney
@ 1999-03-01  0:00             ` Matthew Heaney
  1999-03-02  0:00               ` Nick Roberts
  1 sibling, 1 reply; 128+ messages in thread
From: Matthew Heaney @ 1999-03-01  0:00 UTC (permalink / raw)


"Nick Roberts" <Nick.Roberts@dial.pipex.com> writes:

> One little detail is that the primitive operations of T should all (with
> possible exceptions) be made abstract, since T is only a 'signature' type,
> e.g.:
> 
> package P is
> 
>   type T (<>) is abstract tagged limited private;
> 
>   <primitive ops (abstract)>
> 
>   type T_Access is access all T'Class;
> 
>   function Ref return T_Access is abstract;

This is wrong.  Function Ref is NOT a primitive operation for type T.
It's just a way of returning a pointer to the object declared in the
body.

To use the scheme I've shown, you'd have to do this:

declare
  Singleton : Singleton_Type renames Ref.all;
begin
  Do_Something (Singleton);
  Do_Something_Else (Singleton);
...
end;

A simpler technique is to make the primitive operations of the type take
access parameters, so then you won't have to dereference the pointer:

  function Singleton return T_Access;
...

  Do_Something (Singleton);
  Do_Something_Else (Singleton);


  




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

* Re: Can't export object of private type
  1999-02-26  0:00           ` robert_dewar
  1999-02-26  0:00             ` bourguet
  1999-02-26  0:00             ` dennison
@ 1999-03-01  0:00             ` Stephen Leake
  1999-03-01  0:00             ` Don Harrison
  3 siblings, 0 replies; 128+ messages in thread
From: Stephen Leake @ 1999-03-01  0:00 UTC (permalink / raw)


robert_dewar@my-dejanews.com writes:

> The advantage of private parts is of course the nice
> compartmentalization. Indeed we have on the drawing boards
> for GNAT a feature to have the private parts in separate
> files which will be very handy for target specialization
> and indeed for general abstraction.

This would help in a situation I just encountered. I'm interfacing to
a hardware device, so I've written a thin Ada binding package to the device
driver. I'd like to make that thin binding private, so normal users
can't use it. But I'd also like to use it in the private part of the
public, thick binding:

package SBS_Device is
    pragma Pure;
    -- just a root package
end SBS_Device;

private package SBS_Device.Thin is

    type Low_Level_Device_Type is record
	...
    end record;

end SBS_Device.Thin;


with SBS_Device.Thin; -- illegal!
package SBS_Device.Thick is

    type Device_Type is private;

    ...

private

    type Device_Type is record
	Low_Level : SBS_Device.Thin.Low_Level_Device_Type;
	...
    end record;
end SBS_Device.Thick;

"with SBS_Device.Thin" is illegal, because it's a private package.

If the private part of SBS_Device.Thick were in a separate file, I
could put the with clause there, and everybody would be happy.

In my code, I made Low_Level a pointer, and deferred the full type to
the body, where I can with SBS_Device.Thin.

Perhaps an alternate solution would be to allow the keyword "private"
in context clauses:

with private SBS_Device.Thin;
package SBS_Device.Thick is ...

The semantics being that the private package is only allowed to be
referenced in the private part.

-- Stephe




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

* Re: Can't export object of private type
  1999-03-01  0:00           ` Nick Roberts
@ 1999-03-01  0:00             ` Matthew Heaney
  1999-03-01  0:00             ` Matthew Heaney
  1 sibling, 0 replies; 128+ messages in thread
From: Matthew Heaney @ 1999-03-01  0:00 UTC (permalink / raw)


"Nick Roberts" <Nick.Roberts@dial.pipex.com> writes:

> Matthew's solution is quite like mine (essentially one package per singleton
> object), except that he actually employs Ada 95's tagged type dynamic
> polymorphism mechanism -- which I strived to avoid (purely for didactic
> reasons, of course ;-) -- producing (probably) a far neater solution.


I strive to avoid it to, but one of the constraints on a solution was
that it use polymorphism.






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

* Re: Can't export object of private type
  1999-02-25  0:00     ` Don Harrison
                         ` (3 preceding siblings ...)
  1999-02-28  0:00       ` Matthew Heaney
@ 1999-03-01  0:00       ` Tom Moran
  1999-03-02  0:00         ` Matthew Heaney
  4 siblings, 1 reply; 128+ messages in thread
From: Tom Moran @ 1999-03-01  0:00 UTC (permalink / raw)


>  1) Have only one instance
>  2) Are polymorphic
I've probably missed something, but does "Are polymorphic" mean the
user can define a descendant type?  In which case he can create an
object of that new type, or in fact multiple objects of that type,
each of which "is" an instance of the original type, contradicting
requirement (1).  No?




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

* Re: Can't export object of private type
  1999-02-27  0:00           ` Nick Roberts
@ 1999-03-01  0:00             ` Don Harrison
  1999-03-02  0:00               ` Matthew Heaney
  1999-03-01  0:00             ` Don Harrison
  1 sibling, 1 reply; 128+ messages in thread
From: Don Harrison @ 1999-03-01  0:00 UTC (permalink / raw)


Nick Roberts wrote:

:One needs to make a distinction between a design concept and the
:implementational mechanism of that design concept, and not make the mistake
:of thinking that a particular design is inextricably wedded to a particular
:mechanism. ..

I agree; there's a difference. There is always a semantic gap between design 
and implementation in a particular language. Better languages, IMO, are those 
where that gap is uniformly narrow. For Ada, I think the gap is quite wide 
in places (eg. polymorphic singletons) and narrow in others (eg. low-level 
mapping).


-- 
Don (Harrison).   donh at syd.csa.com.au






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

* Re: Can't export object of private type
  1999-03-01  0:00               ` Nick Roberts
@ 1999-03-01  0:00                 ` Don Harrison
  1999-03-02  0:00                   ` Matthew Heaney
  0 siblings, 1 reply; 128+ messages in thread
From: Don Harrison @ 1999-03-01  0:00 UTC (permalink / raw)


Nick Roberts wrote:

:I think, possibly, you're missing the point, Don!  

Yes, you're right. Sorry about that.

What was missing was the ability to derive a class hierachy of singletons 
and dispatch on the exported objects. This is what I meant by:

>   2) Are polymorphic

Sorry if that wasn't clear enough initially.

:Planet_Id is only an
:identifier of a planet, not the planet itself.  There is only one instance
:of each planet -- kept in terms of variables within (the body of) each
:planet package -- and the corresponding Planet_Id simply gives access to the
:planet.  It's just like having a single object with potentially many access
:values pointing to it; I'm just using integers (type Planet_Id) instead of
:access values.

Got you.

:Again, you must not confuse design with implementation: I'm using packages
:here instead of types, and integers instead of access values.  But these are
:mere implementational details, and nothing to do with the design.  The
:design is: single objects (the planet packages); polymorphic access to them
:(via planet ids and the package Dynamic_Planet).  The 'objects' in our
:design do not have to be objects in implementation (we use packages
:instead); the 'access' values in our design do not have to be access values
:in our implementation (we use integers instead).

Sure. What I'm trying to acheive is a set of implementation techniques for 
OO design that:

  a) Are consistent at least from the perspective of client code. 
     For example, everything that is an object (including singletons) 
     *looks like* an object (and not a module).
  b) Map as directly as possible from the design.
  c) Are idiomatic Ada.

:Hope this clarifies things.

It does.


-- 
Don (Harrison).   donh at syd.csa.com.au






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

* Re: Can't export object of private type
  1999-02-26  0:00           ` fraser
@ 1999-03-01  0:00             ` Don Harrison
  1999-03-01  0:00               ` Matthew Heaney
  0 siblings, 1 reply; 128+ messages in thread
From: Don Harrison @ 1999-03-01  0:00 UTC (permalink / raw)


Fraser wrote:

:I nearly cried when nospam@thanks.com.au said:
          ^^^^^
?

:>What about "procedure Do_Something (S : access Singleton_Type)", to
:>avoid a bunch of S.all's everywhere.

:>:I just love the way Ada compilers fill in .all for me.  
:
:>Can you give an example?
:
:Sure.  This is an idiom I use all the time (well, until I wrote a generic dynamic
:array package, but that's another story):
:
:   type Array_Type is array (Positive range <>) of Integer;
:   type Array_Access is access Array_Type;
:
:   X : Array_Access;
:   Y : Integer;
:   Z : Array_Type (1 .. Size);
:begin
:
:   X := new Array_Type'(1 .. Size);
:
:   Y := X (3);     --  same as X.all (3)
:
:   Z := X.all;     --  .all required here
:end;
:
:Subprogram access types are similar.  

Okay, got you - the combination of formal access-parameters and implicit 
dereferencing means that no client should have to explicitly dereference.

:Bertrand Meyer goes into this sort of thing
:in his Eiffel book, but I can't remember the term he used. You know, the bit
:about everything being accessed the same way, regardless of the underlying type.

Yes, although I also forget his term for it. The little syntactic sugar 
Ada offers helps compensate for the more typical situation of enforced 
literal-ness. For example, having to bother with the difference between:

  - An object and a reference to it.
  - A tagged type and a 'class' rooted at that type.

Given Ada's requirement for reliability, such literal-ness isn't surprising.

It's also interesting to note that some of Eiffel's weaknesses are a result 
of glossing over such distinctions.

:I think Eiffel (at least in its first incarnation, I haven't checked the language's
:revision history) goes a little overboard in its race for purity (but that's another
:article).  

That view seems to be widely held in Ada circles. However, I can't help 
noticing that purity very neatly deals with the singleton issue (.. and a 
number of other Ada problems).  :)
 
:Not having to worry about whether something's an array or an array access
:when you index it is a small plus, but it's representative of a wider philosopher.

Agree.


-- 
Don (Harrison).   donh at syd.csa.com.au






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

* Re: Can't export object of private type
  1999-02-26  0:00           ` Samuel Mize
@ 1999-03-01  0:00             ` Don Harrison
  1999-03-01  0:00               ` Matthew Heaney
  1999-03-02  0:00               ` fraser
  0 siblings, 2 replies; 128+ messages in thread
From: Don Harrison @ 1999-03-01  0:00 UTC (permalink / raw)


Sam Mize wrote:

:Don Harrison <nospam@thanks.com.au> wrote:
:a lot, with the following side issue at the end:
:
:> :I just love the way Ada compilers fill in .all for me.  
:> 
:> Can you give an example?
:
:Sure.  If the access value denotes a record value, you don't have
:to put ".all" to access the record's fields:
:
:    F := Access_Value.all.Field;
:    F := Access_Value.Field;
:
:This requires different syntax in C ("@" and "." versus "->", IIRC).

Doesn't sound nice. :)

:In a case like this, it's unlikely you are making a mistake, so Ada
:assumes you want the implicit ".all".

I guess I was aware of implicit dereferencing. What I didn't appreciate 
was the value of combining it with formal access-parameters.

:On the other hand, mis-using a pointer to a scalar is a common
:error, so Ada doesn't infer any de-references -- you have to do
:them manually.

Wasn't aware of this restriction - makes sense.


-- 
Don (Harrison).   donh at syd.csa.com.au






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

* Re: Can't export object of private type
  1999-03-01  0:00             ` Don Harrison
@ 1999-03-01  0:00               ` Matthew Heaney
  0 siblings, 0 replies; 128+ messages in thread
From: Matthew Heaney @ 1999-03-01  0:00 UTC (permalink / raw)


nospam@thanks.com.au (Don Harrison) writes:

> That view seems to be widely held in Ada circles. However, I can't help 
> noticing that purity very neatly deals with the singleton issue (.. and a 
> number of other Ada problems).  :)

I think the "problem" is that the proper idioms for implementing
singleton abstractions in Ada aren't well-known.  The articles I've been
submitting to the ACM patterns archive are an attempt to overcome this.

<http://www.acm.org/archives/patterns.html>

As I explained in my previous posts in this thread, a polymorphic
singleton can be implemented in Ada by using a tagged, limited, and
indefinite type, and declaring an instance of that type in the package
body.

The singleton package exports a function that returns a pointer to that
object (if you need an object) or just returns the object (if you need a
value).

declare
  Singleton : Singleton_Type'Class renames Ref.all;
begin
  <call dispatching operations on Singleton>
end;

This is how you implement Eiffel's once-functions in Ada95.

Note that the languages have made different decisions here: Eiffel moved
once-functions directly into the language, while Ada95 gives you the
primitives for assembling them yourself.




  




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

* Re: Can't export object of private type
  1999-03-01  0:00             ` Don Harrison
@ 1999-03-01  0:00               ` Matthew Heaney
  1999-03-02  0:00               ` fraser
  1 sibling, 0 replies; 128+ messages in thread
From: Matthew Heaney @ 1999-03-01  0:00 UTC (permalink / raw)


nospam@thanks.com.au (Don Harrison) writes:

> I guess I was aware of implicit dereferencing. What I didn't appreciate 
> was the value of combining it with formal access-parameters.

I did this in my implementation of the Interpreter pattern, in the Oct
98 ACM patterns archives.

<http://www.acm.org/archives/patterns.html>

You also use the technique to free objects designated by a pointer to a
class-wide type.  Most of my recent articles have been implemented this
way (do a substring search for Do_Free).



Interpreter

WHY ACCESS PARAMETERS?

All expression objects are referred to via an access object.  Since
there are only references to objects, all the primitive operations for
the type take access T as the type.  This way, the client doesn't have
to say X.all everywhere -- she can invoke an operation by just using X
directly.


Smart Pointers

I was able to simplify this example by using smart pointers, which
provide automatic garbage collection.  You can read all about it in the
article "Smart Pointers," in the Feb 99 archive.








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

* Re: Can't export object of private type
  1999-02-27  0:00           ` Nick Roberts
  1999-03-01  0:00             ` Don Harrison
@ 1999-03-01  0:00             ` Don Harrison
  1999-03-01  0:00               ` Matthew Heaney
                                 ` (2 more replies)
  1 sibling, 3 replies; 128+ messages in thread
From: Don Harrison @ 1999-03-01  0:00 UTC (permalink / raw)


Nick Roberts wrote:

:   package Planetary is
       ...
:      type Planet_Id is private;
       ...
:   private
:      ...
:   end Planetary;

The problem here is that you lose the property of having a single instance:

>   1) Have only one instance

Since Planet_Id is exported, anyone can declare an object of that type. 
We want to ensure there is only a single instance shared by all clients.

:Another possible scheme that might suit you is: (a) declare a limited tagged
:type which is derived from Finalization.Limited_Controlled; (b) implement
:Initialize so that it increments a counter (which is itself initialized to
:0), and if it goes above 1 (or some other number), raise an exception; (c)
:implement Finalize so it decrements the counter.  This way you can
:polymorphise the type as normal, but be sure no more than one object of the
:type exists at any one time.

Interesting idea. However, static enforcement would be preferable. We should 
expand 1):

>   1) Have only one instance (enforced statically)


-- 
Don (Harrison).   donh at syd.csa.com.au






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

* Re: Can't export object of private type
  1999-03-01  0:00             ` Don Harrison
@ 1999-03-01  0:00               ` Matthew Heaney
  1999-03-01  0:00                 ` Nick Roberts
  1999-03-01  0:00               ` Nick Roberts
  1999-03-03  0:00               ` Robert A Duff
  2 siblings, 1 reply; 128+ messages in thread
From: Matthew Heaney @ 1999-03-01  0:00 UTC (permalink / raw)


nospam@thanks.com.au (Don Harrison) writes:

> Nick Roberts wrote:
> 
> :   package Planetary is
>        ...
> :      type Planet_Id is private;
>        ...
> :   private
> :      ...
> :   end Planetary;
> 
> The problem here is that you lose the property of having a single instance:
> 
> >   1) Have only one instance
> 
> Since Planet_Id is exported, anyone can declare an object of that type. 
> We want to ensure there is only a single instance shared by all clients.


Then declare the Plant_Id type as limited and indefinite:

package Planetary is

  type Planet_Id (<>) is limited private;

...
end Planetary;





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

* Re: Can't export object of private type
  1999-02-26  0:00           ` robert_dewar
                               ` (2 preceding siblings ...)
  1999-03-01  0:00             ` Stephen Leake
@ 1999-03-01  0:00             ` Don Harrison
  1999-03-01  0:00               ` robert_dewar
  3 siblings, 1 reply; 128+ messages in thread
From: Don Harrison @ 1999-03-01  0:00 UTC (permalink / raw)


Robert_dewar wrote:

:In article <F7r2DF.23y@syd.csa.com.au>,
:  nospam@thanks.com.au wrote:
:> Because *non-recursive* declarations imply a partial
:> ordering, a valid elaboration sequence can be determined
:> for them, irrespective of declaration order.
:
:I know that seems reasonable for simple cases, but this
:approach simply will not work, it is recursively
:undecidable in the general case what ordering should be
:used, since it depends on computational paths.

By "computational paths", do you mean:

  - Functions called to initialise package variables, and
  - Procedures called in package blocks?

I may be missing something here, but..

Wouldn't any declarations used in such operations simply be ordered ahead
of the declaration that uses them in the elaboration order? You wouldn't 
need to order the branch declarations WRT each other because, you only 
need a partial ordering, rather than a total one. 

The only problem would seem to be where the ordering dictated by different 
declarations are mutually contradictory. This would yield a compile error. 

:Linear elaboration is a model that enormously simplifies
:the semantics of the language, ..

I can imagine elaboration problems would be even worse without it. Perhaps,
it makes them tolerable.

:(note that you do NOT have a formal definition of what
:you mean by recursive here, and you will find that any
:attempt to formalize this definition will fail.)

  "A recursive declaration is one which is composed of at least 
   one declaration defined (transitively) in terms of the 
   declaration being considered."


-- 
Don (Harrison).   donh at syd.csa.com.au






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

* Re: Can't export object of private type
  1999-02-28  0:00               ` dewar
@ 1999-03-01  0:00                 ` bourguet
  0 siblings, 0 replies; 128+ messages in thread
From: bourguet @ 1999-03-01  0:00 UTC (permalink / raw)


In article <7bagrq$l6c$1@nnrp1.dejanews.com>,
  dewar@gnat.com wrote:
> In article <7b6f9k$at2$1@nnrp1.dejanews.com>,
>   bourguet@my-dejanews.com wrote:
> > Well, this is a feature I'd like, especially if the
> > compilation of a unit "withing" the package can be
> > compiled (and code generated)
> > without the private part. More or less like inter package
> > inline
> > is currently handled by gnat: you have a performance gain
> > if you accept
> > the dependancy but you may prefer the flexibility of the
> > independancy...
> > well I'd even accept that all the program have to be
> > compiled with the
> > same mode.
>
> Interesting idea. Of course you cannot generate code
> without the private part present (or at least not in any
> reasonably efficient or practical manner).

What I was thinking for the "don't use knowledge about private
parts" mode of code generation would be the equivalent of:

type X is private;

...

private
   type X_Decl;
   type X_Access is access X_Decl;
   type X is new Ada.Finalization.Controlled with record
      Value: X_Access;
   end record;

I know some people working in C++ who advice to always use the
equivalent.

Yours,

-- Jean-Marc

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    




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

* Re: Can't export object of private type
  1999-02-27  0:00         ` Brian Rogoff
@ 1999-03-01  0:00           ` robert_dewar
  0 siblings, 0 replies; 128+ messages in thread
From: robert_dewar @ 1999-03-01  0:00 UTC (permalink / raw)


In article
<Pine.BSF.4.05.9902271942010.1050-100000@shell5.ba.best.com
>,
  Brian Rogoff <bpr@shell5.ba.best.com> wrote:
> On Thu, 25 Feb 1999 robert_dewar@my-dejanews.com wrote:
> > ... snip ...
> >
> > Now my own design preference would have been to avoid
> > the
> > separate private part, and just put a private keyword >
> > on selected declarations.
>
> I suppose that would be equivalent to an upwardly
> compatible extension of Ada which allowed interleaving of
> public and private sections, like C++.

Well I suppose that technically this would be a compatible
extension, but I cannot imagine anything more inappropriate
than having BOTH mechanisms in the same language, that
would just be a confusing mess, so I am not FOR A MOMENT
suggesting a change to the language here, merely musing
about what might have been.

And I must say, that the argument is not clear. In
particular, especially if you have the ability to separate
off private parts physically, e.g. into a separate file,
there are tremendous advantages in having the private part
be separate. For example, it is very typical that the spec
proper is target dependent, but the private part needs
specialization.

So I am not at all sure that I am clearly in favor of my
original note, quoted above, here. The issues are basically
that this would simplify the semantics considerably, but
there would be a real cost in abstraction capabilities.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    




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

* Re: Can't export object of private type
  1999-03-01  0:00             ` Don Harrison
  1999-03-01  0:00               ` Matthew Heaney
@ 1999-03-01  0:00               ` Nick Roberts
  1999-03-01  0:00                 ` Don Harrison
  1999-03-03  0:00               ` Robert A Duff
  2 siblings, 1 reply; 128+ messages in thread
From: Nick Roberts @ 1999-03-01  0:00 UTC (permalink / raw)


I think, possibly, you're missing the point, Don!  Planet_Id is only an
identifier of a planet, not the planet itself.  There is only one instance
of each planet -- kept in terms of variables within (the body of) each
planet package -- and the corresponding Planet_Id simply gives access to the
planet.  It's just like having a single object with potentially many access
values pointing to it; I'm just using integers (type Planet_Id) instead of
access values.

Again, you must not confuse design with implementation: I'm using packages
here instead of types, and integers instead of access values.  But these are
mere implementational details, and nothing to do with the design.  The
design is: single objects (the planet packages); polymorphic access to them
(via planet ids and the package Dynamic_Planet).  The 'objects' in our
design do not have to be objects in implementation (we use packages
instead); the 'access' values in our design do not have to be access values
in our implementation (we use integers instead).

Or is it me who is missing the missing the point? :-)

Hope this clarifies things.

-------------------------------------
Nick Roberts
-------------------------------------







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

* Re: Can't export object of private type
  1999-03-01  0:00               ` Matthew Heaney
@ 1999-03-01  0:00                 ` Nick Roberts
  0 siblings, 0 replies; 128+ messages in thread
From: Nick Roberts @ 1999-03-01  0:00 UTC (permalink / raw)


See my other post: what Matthew suggests would work if Planet_Id needed to
be protected, but it doesn't (since it's only purpose is to provide access
to planets, which are already protected inside package bodies).  (Unless I'm
missing out on something, myself ;-)

-------------------------------------
Nick Roberts
-------------------------------------








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

* Re: Can't export object of private type
  1999-02-28  0:00         ` Matthew Heaney
@ 1999-03-01  0:00           ` Nick Roberts
  1999-03-01  0:00             ` Matthew Heaney
  1999-03-01  0:00             ` Matthew Heaney
  1999-03-01  0:00           ` Samuel Mize
  1 sibling, 2 replies; 128+ messages in thread
From: Nick Roberts @ 1999-03-01  0:00 UTC (permalink / raw)


Some (purists!) might say that using a type at all gives a "false sense of
abstraction" (because it is 'idiomatic' that a type implies many objects,
rather than just one).  Frankly, I find Matthew's solution so neat I
wouldn't subscribe to that point of view myself.

One little detail is that the primitive operations of T should all (with
possible exceptions) be made abstract, since T is only a 'signature' type,
e.g.:

package P is

  type T (<>) is abstract tagged limited private;

  <primitive ops (abstract)>

  type T_Access is access all T'Class;

  function Ref return T_Access is abstract;

private

  <junk>

end P;

[Aside: the 'possible exceptions' are (almost always) procedures (a) for
which it would be particularly convenient to provide a 'do nothing'
procedure to be automatically inherited (by the majority of derived types),
or (b) which provide the 'backstop' on a call-the-parent chain.]

Matthew's solution is quite like mine (essentially one package per singleton
object), except that he actually employs Ada 95's tagged type dynamic
polymorphism mechanism -- which I strived to avoid (purely for didactic
reasons, of course ;-) -- producing (probably) a far neater solution.

-------------------------------------
Nick Roberts
-------------------------------------








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

* Re: Can't export object of private type
  1999-03-01  0:00             ` Don Harrison
@ 1999-03-01  0:00               ` robert_dewar
  1999-03-03  0:00                 ` Don Harrison
  0 siblings, 1 reply; 128+ messages in thread
From: robert_dewar @ 1999-03-01  0:00 UTC (permalink / raw)


In article <F7wKy8.4Jq@syd.csa.com.au>,
  nospam@thanks.com.au wrote:
>   "A recursive declaration is one which is composed of at
>    least  one declaration defined (transitively) in terms
>    of the declaration being considered."

This is not even close to a formal definition (what
does composed mean? what does defined mean? what does
transitively mean? what does "in terms of" mean?

In fact it is so vague that I am no longer even clearly
sure of what you have in mind (and I am quite sure that
you will have trouble formalizing it).

If you want to try, use RM defined terms only, and use
them precisely!

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    




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

* Re: Can't export object of private type
  1999-03-02  0:00                 ` Matthew Heaney
@ 1999-03-02  0:00                   ` nabbasi
  1999-03-02  0:00                     ` Matthew Heaney
  1999-03-03  0:00                   ` Don Harrison
  1 sibling, 1 reply; 128+ messages in thread
From: nabbasi @ 1999-03-02  0:00 UTC (permalink / raw)


In article <m3678k6v1x.fsf@mheaney.ni.net>, Matthew says...
 
>I'm working on another pattern now that was inspired by this thread.  An
>abstract factory, implemented using smart pointers, is used to
>initialize a singleton instance of a limited and indefinite type.  Whew!
>I'll post an announcement on CLA once it has been submitted (probably
>tomorrow or the day after.)

Matthew, you should write a book "Patterns in Ada" with all this good stuff,
with plenty of real life, usage examples of using these patterns. 

Nasser

 




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

* Re: Can't export object of private type
  1999-03-01  0:00             ` Don Harrison
  1999-03-01  0:00               ` Matthew Heaney
@ 1999-03-02  0:00               ` fraser
  1999-03-03  0:00                 ` Don Harrison
  1 sibling, 1 reply; 128+ messages in thread
From: fraser @ 1999-03-02  0:00 UTC (permalink / raw)


I nearly cried when nospam@thanks.com.au said:

(Oh, it's nothing personal (the tagline) btw, I'm just very sensitive
like that.  Maybe it's time to change it)

>Sam Mize wrote:

>:This requires different syntax in C ("@" and "." versus "->", IIRC).

>Doesn't sound nice. :)

It sucks.  Imagine, for a moment, deciding to change a stack object to
an allocated one.  It's happened to me, and it hurts.  A lot.


[Sam]
>:In a case like this, it's unlikely you are making a mistake, so Ada
>:assumes you want the implicit ".all".

>:On the other hand, mis-using a pointer to a scalar is a common
>:error, so Ada doesn't infer any de-references -- you have to do
>:them manually.

I think it goes deeper than that.  From a data abstraction point of view,
you're using an object as a gateway, or a guide, to find what you really
want, a record component or an array element for example.  Whether the
gateway is on the stack or on the heap (I'm simplifying here)
should make no difference to the code that uses it -- it's the same
thing.  Not from the compiler's POV of course, but the compiler's job
is to make my life easier.

An access to a scalar is a special case of an access to a general type, 
and of course X is not equivalent to X.all (the equivalence only works
when you're using the object to get somewhere else).

>I guess I was aware of implicit dereferencing. What I didn't appreciate 
>was the value of combining it with formal access-parameters.

Oh, yes indeedy woo.  The day it dawned on me that you could do that was
a good day.  Imagine, if you will, a heterogeneous n-ary tree of tagged
objects with a common ancestor.  Even more specifically, call it an
abstract syntax tree.  The ancestor type might look like this:

   type Abstract_Tree_Node is abstract tagged private;
   procedure Analyse (T : access Abstract_Tree_Node) is abstract;
   procedure Generate_Code (T : access Abstract_Tree_Node) is abstract;
   procedure Execute (T : access Abstract_Tree_Node) is abstract;

   type Abstract_Tree is access all Abstract_Tree_Node'Class;

A statement node could be like this:

   type Statement_Node is abstract new Abstract_Tree_Node with private;
 
   type While_Statement_Node is new Statement_Node with
      record
         Name      : Identifier_Name;
         Condition : Abstract_Tree;
         Loop_Body : Abstract_Tree;
      end record;

   procedure Analyse (T : access While_Statement);
   procedure Generate_Code (T : access While_Statement);
   procedure Execute (T : access While_Statement);
   
The body of the three primitive operations would do some stuff, and make
dispatching calls to Condition and Loop_Body.


   procedure Generate_Code (T : access While_Statement) is
      Label_1, Label_2 : Label;
   begin
      Label_1 := Next_Label;
      Label_2 := Next_Label;

      Generate_Label (Label_1);
      Generate_Code (T.Condition);
      Generate_Branch_On_Zero (Label_2);
      Generate_Code (T.Loop_Body);
      Generate_Branch (Label_1);
      Generate_Label (Label_2);

   end Generate_Code;
 

I've used this sort of thing on, um, about four or five systems, mainly to
test ideas on compilation techniques, and it's not quite as beautiful as it
should be, but it's interesting.  Like anything else, it works well in
general, but the details are what gets you.  I mean, try analysing an
Ada expression using a single Analyse procedure, and without a bunch of
expression-specific abstraction-breaking data shunting.

Now, where's that coffee.

Fraser.
(remove the obvious bits for my real email address)




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

* Re: Can't export object of private type
  1999-03-02  0:00                   ` nabbasi
@ 1999-03-02  0:00                     ` Matthew Heaney
  0 siblings, 0 replies; 128+ messages in thread
From: Matthew Heaney @ 1999-03-02  0:00 UTC (permalink / raw)


nabbasi@pacbell.net writes:

> In article <m3678k6v1x.fsf@mheaney.ni.net>, Matthew says...
>  
> >I'm working on another pattern now that was inspired by this thread.  An
> >abstract factory, implemented using smart pointers, is used to
> >initialize a singleton instance of a limited and indefinite type.  Whew!
> >I'll post an announcement on CLA once it has been submitted (probably
> >tomorrow or the day after.)
> 
> Matthew, you should write a book "Patterns in Ada" with all this good stuff,
> with plenty of real life, usage examples of using these patterns. 

That's my plan.  In the mean-time, you can find the stuff that'll be in
the book, in the ACM patterns archive.

<http://www.acm.org/archives/patterns.html>






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

* Re: Can't export object of private type
  1999-03-01  0:00             ` Matthew Heaney
@ 1999-03-02  0:00               ` Nick Roberts
  0 siblings, 0 replies; 128+ messages in thread
From: Nick Roberts @ 1999-03-02  0:00 UTC (permalink / raw)


Indeed I boobed with the function Ref.  Sorry.

However, I think (and I may need correction on this ;-), Matthew's
formulation is also wrong, and actually more complicated than it needs to
be.  I don't think there's any need for a function Ref where Matt puts it;
all you need is the following:

   package Planetary is
      type Planet(<>) is abstract tagged limited private;
      type Planet_Access is access all Planet'Class;
      [general planetary primitive operations (all abstract)]
   private
      ...
   end Planetary;

   package Planetary.Mercury is
      type Planet_Mercury(<>) is abstract new Planet with private;
      type Mercury_Access is access all Planet_Mercury'Class;
      [specifically Mercurial primitive operations (all abstract)]
      function The_Planet return Mercury_Access;
   private
      ...
   end Planetary.Mercury;

   -- so on for all the planets

Inside the bodies of the planet packages, you would declare a (concrete)
type derived from the planet's abstract type, and then declare (and
implement) all the promised operations for it.  Finally, you would declare
an aliased object of this type, and then implement the The_Planet function
to simply return a value which refers to this object (using the Access
attribute).

I'm fairly sure this formulation is actually right (finally).  We get there
in the end!

This method not only leverages the fairly powerful dynamic polymorphism
functionality Ada 95 has to offer, but it is also (as a general methodology)
flexible in terms of whether a (future) planet is actually a single entity,
or a binary system, or a whole chain of asteroids.  In the latter cases, you
might supply functions The_Planet_1 and The_Planet_2, or parametize the
function The_Planet accordingly.

You could even supply a function to create new planets, e.g.:

   type Spacestation(<>) is abstract new Planet with private;
   function New_Station (Cost: Megadollars) return Spacestation;

where the user is able to create an (initialised) object, e.g.:

   Alpha: Spacestation := New_Station(US_Spare_Cash+Russian_Spare_Cash);

-------------------------------------
Nick Roberts
-------------------------------------








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

* Re: Can't export object of private type
  1999-03-01  0:00       ` Tom Moran
@ 1999-03-02  0:00         ` Matthew Heaney
  1999-03-02  0:00           ` Tom Moran
  1999-03-03  0:00           ` Don Harrison
  0 siblings, 2 replies; 128+ messages in thread
From: Matthew Heaney @ 1999-03-02  0:00 UTC (permalink / raw)


tmoran@bix.com (Tom Moran) writes:

> >  1) Have only one instance
> >  2) Are polymorphic
> I've probably missed something, but does "Are polymorphic" mean the
> user can define a descendant type?  In which case he can create an
> object of that new type, or in fact multiple objects of that type,
> each of which "is" an instance of the original type, contradicting
> requirement (1).  No?

No.  If you make the type limited and indefinite, no one outside the
package can create an instance.

The root package of the subsystem exports an instance function that
returns a pointer to the singleton object declared in the body.  Because
the pointer designates the class-wide type, the object can be any type
in the class.

This is an example of a package with'ing its own child.

The primitive operations of the type are all access parameters.  When
you invoke an operation of the type, you pass the result of the instance
function to the operation.  That way, you don't even have to dereference
the return value (which is a pointer).

This is how you implement a "once function" in Ada.  The difference is
that you don't need to put anything on the heap, which is how Ada was
designed.

This is one of the reasons why there's no compelling reason to have a
garbage collector in Ada.

All four goals are thus satisfied.













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

* Re: Can't export object of private type
  1999-03-01  0:00             ` Don Harrison
@ 1999-03-02  0:00               ` Matthew Heaney
  0 siblings, 0 replies; 128+ messages in thread
From: Matthew Heaney @ 1999-03-02  0:00 UTC (permalink / raw)


nospam@thanks.com.au (Don Harrison) writes:

> There is always a semantic gap between design and implementation in a
> particular language. Better languages, IMO, are those where that gap
> is uniformly narrow. For Ada, I think the gap is quite wide in places
> (eg. polymorphic singletons) and narrow in others (eg. low-level
> mapping).

I disagree about the polymorphic singletons.  The spec looks like this:


package Singletons is

  type Root_Singleton_Type (<>) is abstract tagged limited null record;

  procedure Do_Something
   (Singleton : access Root_Singleton_Type) is abstract;

  <other primitive operations>


  type Singleton_Access is access all Root_Singleton_Type'Class;

  function Singleton return Singleton_Access;

end;


I wouldn't describe the semantic gap as "quite wide."  The problem is
that few Ada programmers have learned the limited-and-indefinite
idiom.  

So this idiom just needs to be publicized.  You can find examples of
this idiom and others in the ACM patterns archive.

<http://www.acm.org/archives/patterns.html>
















  




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

* Re: Can't export object of private type
  1999-03-02  0:00         ` Matthew Heaney
@ 1999-03-02  0:00           ` Tom Moran
  1999-03-02  0:00             ` Matthew Heaney
  1999-03-03  0:00           ` Don Harrison
  1 sibling, 1 reply; 128+ messages in thread
From: Tom Moran @ 1999-03-02  0:00 UTC (permalink / raw)


>No.  If you make the type limited and indefinite, no one outside the
>package can create an instance.
But given such a type T, if I'm outside and make
  type Son_Of_T is new T with ...
how can I create an object of type Son_Of_T, and if such an object
cannot be created, of what use is Son_Of_T?





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

* Re: Can't export object of private type
  1999-03-02  0:00           ` Tom Moran
@ 1999-03-02  0:00             ` Matthew Heaney
  1999-03-02  0:00               ` Tom Moran
  1999-03-03  0:00               ` Can't export object of private type Don Harrison
  0 siblings, 2 replies; 128+ messages in thread
From: Matthew Heaney @ 1999-03-02  0:00 UTC (permalink / raw)


tmoran@bix.com (Tom Moran) writes:

> >No.  If you make the type limited and indefinite, no one outside the
> >package can create an instance.
> But given such a type T, if I'm outside and make
>   type Son_Of_T is new T with ...
> how can I create an object of type Son_Of_T, and if such an object
> cannot be created, of what use is Son_Of_T?

The question is wrong.  There's no such thing as "being outside" and
declaring a derived type.

If there is a derived type, it's within the package hierarchy:

package P is

   type T (<>) is abstract tagged limited private;

   procedure Op (O : access T) is abstract;

private

   type T is abstract tagged limited null record;

end P;


package P.C is

   type NT is new T with private;

   procedure Op (O : access NT);


   type NT_Access is access all NT;

   function Singleton return NT_Access;


private

   type NT is new T with null record;

end;


package body P.C is

   O : aliased NT;


   procedure Op (O : access NT) is
   begin
      null;
   end;

   function Singleton return NT_Access is
   begin
      return O'Access;
   end;

end;


When I try to declare an instance of P.C.NT:

with P.C;
procedure Test_P is

  O : P.C.NT;

begin

  null;

end;


I get the following error:

gnatf -x5 /home/matt/test_p.adb
test_p.adb:4:10: unconstrained subtype not allowed (need initialization)

But within the package hierarchy, I'm free to declare instances of the
type (see the body of P.C), because I have privileged access to the
representation of the type (which of course, is _not_ indefinite).

We can get rid of the compiler diagnostic, by using the singleton instance:

with P.C; use P.C;
procedure Test_P is
begin

  Op (Singleton);

end;


We have used the features the language provides us to design a type
hierarchy such that, the client must use the singleton instance(s).  He
has no other choice in the matter, which is the intended effect.





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

* Re: Can't export object of private type
  1999-03-02  0:00             ` Matthew Heaney
@ 1999-03-02  0:00               ` Tom Moran
  1999-03-02  0:00                 ` Matthew Heaney
  1999-03-03  0:00               ` Can't export object of private type Don Harrison
  1 sibling, 1 reply; 128+ messages in thread
From: Tom Moran @ 1999-03-02  0:00 UTC (permalink / raw)


>If there is a derived type, it's within the package hierarchy:

>package P is

>   type T (<>) is abstract tagged limited private;
 But what about
   with P;
   package Q is
      type Son_Of_T is new P.T with ...
Or does the original question *only* refer to 
>package P.C is

>   type NT is new T with private;
In which case, why even have T in the public part of P?  It could be
in the private part, where it's visible to P.C, and not visible to
'outsiders'.  If you restrict T to being extended only in children of
P, then it can be private, and the original question disappears.




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

* Re: Can't export object of private type
  1999-03-02  0:00               ` Tom Moran
@ 1999-03-02  0:00                 ` Matthew Heaney
  1999-03-02  0:00                   ` nabbasi
  1999-03-03  0:00                   ` Don Harrison
  0 siblings, 2 replies; 128+ messages in thread
From: Matthew Heaney @ 1999-03-02  0:00 UTC (permalink / raw)


tmoran@bix.com (Tom Moran) writes:

> >If there is a derived type, it's within the package hierarchy:
> 
> >package P is
> 
> >   type T (<>) is abstract tagged limited private;
>  But what about
>    with P;
>    package Q is
>       type Son_Of_T is new P.T with ...

No, there is no such thing.  Outside the package hierarchy, there'd be
no way to create an instance of Son_Of_T.

> Or does the original question *only* refer to 
> >package P.C is

Yes, this is the case.  Derivations only occur in children of P.
 

> >   type NT is new T with private;
> In which case, why even have T in the public part of P?  It could be
> in the private part, where it's visible to P.C, and not visible to
> 'outsiders'.  If you restrict T to being extended only in children of
> P, then it can be private, and the original question disappears.

No.  You're forgetting that clients are still manipulating a singleton
instance of the derived type.  This is a public object, of a public
type, with public operations.  That NT derives from T is a public
feature of the type, not an implementation detail.

Of course, you could do it the way you suggest.  This is sort of an
extreme example, where you have a family of types, and each type in the
family has a singleton instance.  

I don't know why Don wants to do this (I've certainly never had such a
need), but I wanted to show that it is possible, and that in fact the
implementation is relatively simple.

It will take some time for programmers to grok the concept of limited
and indefinite types, and what it's buying you.  I have a few examples
of this idiom in the ACM patterns archive.

<http://www.acm.org/archives/patterns.html>

I'm working on another pattern now that was inspired by this thread.  An
abstract factory, implemented using smart pointers, is used to
initialize a singleton instance of a limited and indefinite type.  Whew!
I'll post an announcement on CLA once it has been submitted (probably
tomorrow or the day after.)













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

* Re: Can't export object of private type
  1999-03-01  0:00                 ` Don Harrison
@ 1999-03-02  0:00                   ` Matthew Heaney
  1999-03-03  0:00                     ` Don Harrison
  1999-03-07  0:00                     ` Ehud Lamm
  0 siblings, 2 replies; 128+ messages in thread
From: Matthew Heaney @ 1999-03-02  0:00 UTC (permalink / raw)


nospam@thanks.com.au (Don Harrison) writes:

> Sure. What I'm trying to acheive is a set of implementation techniques for 
> OO design that:
> 
>   a) Are consistent at least from the perspective of client code. 
>      For example, everything that is an object (including singletons) 
>      *looks like* an object (and not a module).
>   b) Map as directly as possible from the design.
>   c) Are idiomatic Ada.

The state machine package is "idiomatic Ada."  Your a) and c) goals may
be in conflict.

As I have argued in previous posts, don't export a singleton instance of
a type unless you have a compelling need to.  Types should really only
be used to implement an abstraction that has an unbounded number of
instances.

If you know up front how many "instances" of an abstraction you have
--what I call the "well-known objects" pattern-- then a state machine
package is probably the way to go.  

For example, in the embedded systems I build, you just refer to the
abstraction as "digitizer 1" or "depth detector 2" or "target 11", as in

package Digitizers is

  type Digitizer_Id is range 1 .. 2;

  type Digitizer_Mode is (...);

  procedure Set_Mode (Digitizer : Digitizer_Id;
                      Mode      : Digitizer_Mode);

  procedure Acquire (Digitizer : Digitizer_Id);

  procedure Cancel_Acquisition (Digitizer : Digitizer_Id);

...
end Digitizers;


An abstract data type wouldn't buy you very much except syntactic
overhead.

Thinking in terms of packages (or "modules", if you prefer that term) is
fundamental to Ada programming.  If you're using singleton instances of
types everywhere, motivated perhaps by some notion of "purity," then
that may be a sign that you're fighting the language.

In a typical Ada application, some abstractions are implemented as state
machine packages, and some abstractions are implemented as instances of
an abstract data type.  There is nothing odd or unnatural about this.











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

* Re: Can't export object of private type
  1999-03-02  0:00         ` Matthew Heaney
  1999-03-02  0:00           ` Tom Moran
@ 1999-03-03  0:00           ` Don Harrison
  1 sibling, 0 replies; 128+ messages in thread
From: Don Harrison @ 1999-03-03  0:00 UTC (permalink / raw)


Matthew Heaney wrote:

[..]

Agree with the following..

:This is how you implement a "once function" in Ada.  The difference is
:that you don't need to put anything on the heap, which is how Ada was
:designed.
:
:This is one of the reasons why there's no compelling reason to have a
:garbage collector in Ada.
:
:All four goals are thus satisfied.


-- 
Don (Harrison).   donh at syd.csa.com.au






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

* Re: Can't export object of private type
  1999-03-02  0:00                 ` Matthew Heaney
  1999-03-02  0:00                   ` nabbasi
@ 1999-03-03  0:00                   ` Don Harrison
  1999-03-03  0:00                     ` Single Extension; Polymorphic Arrays Nick Roberts
  1 sibling, 1 reply; 128+ messages in thread
From: Don Harrison @ 1999-03-03  0:00 UTC (permalink / raw)


Matt Heaney wrote:

:Of course, you could do it the way you suggest.  This is sort of an
:extreme example, where you have a family of types, and each type in the
:family has a singleton instance.  
:
:I don't know why Don wants to do this (I've certainly never had such a
:need), but I wanted to show that it is possible, and that in fact the
:implementation is relatively simple.

The actual context is..

A family of handlers is needed, each of which processes a specific type of 
data item received over an external interface. 

There should be one such handler per data item type and handlers share 
common behaviour.

The handlers also need to be processed as a group (eg. for resetting state)
so need to be storable in a polymorphic collection which may be processed 
by iterating over its elements.

Hence, the requirement for a family of tagged singletons.

Note, BTW, that the primitive operations for processing data items must 
belong to the handler hierarchy (rather than a parallel data item hierarchy) 
in the interests of faithful modelling. (IMO, implementations in which 
objects process themselves are nonsensical. One such example in the Ada 
Rationale has alerts handling themselves!).

:It will take some time for programmers to grok the concept of limited
:and indefinite types, and what it's buying you.  

They're somewhat tortured souls. Types whose objects:

  a) Must be (initialised when declared so they are constrained), yet
  b) Can't be (initialised by clients because they are limited), so
  c) Aren't (declarable by clients - a) and b) are contradictory for clients).

:I have a few examples
:of this idiom in the ACM patterns archive.
:
:<http://www.acm.org/archives/patterns.html>

Looks like you have some good stuff here. Thanks for publicising it.

:I'm working on another pattern now that was inspired by this thread.  An
:abstract factory, implemented using smart pointers, is used to
:initialize a singleton instance of a limited and indefinite type.  Whew!
:I'll post an announcement on CLA once it has been submitted (probably
:tomorrow or the day after.)

Interesting.


-- 
Don (Harrison).   donh at syd.csa.com.au






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

* Re: Can't export object of private type
  1999-03-02  0:00                   ` Matthew Heaney
@ 1999-03-03  0:00                     ` Don Harrison
  1999-03-03  0:00                       ` Samuel Mize
  1999-03-07  0:00                     ` Ehud Lamm
  1 sibling, 1 reply; 128+ messages in thread
From: Don Harrison @ 1999-03-03  0:00 UTC (permalink / raw)


Matt Heaney wrote:

:nospam@thanks.com.au (Don Harrison) writes:
:
:> Sure. What I'm trying to acheive is a set of implementation techniques for 
:> OO design that:
:> 
:>   a) Are consistent at least from the perspective of client code. 
:>      For example, everything that is an object (including singletons) 
:>      *looks like* an object (and not a module).
:>   b) Map as directly as possible from the design.
:>   c) Are idiomatic Ada.
:
:The state machine package is "idiomatic Ada."  Your a) and c) goals may
:be in conflict.

Where possible, and where it makes sense, I want to leave open the 
possibility of reuse by inheritance as well as aggregation. Simple state 
machines won't allow this flexibility.

:As I have argued in previous posts, don't export a singleton instance of
:a type unless you have a compelling need to.  Types should really only
:be used to implement an abstraction that has an unbounded number of
:instances.
:
:If you know up front how many "instances" of an abstraction you have
:--what I call the "well-known objects" pattern-- then a state machine
:package is probably the way to go.  

Partitioning objects into "well-known" and less-well-known :)  will always 
be somewhat arbitrary. However, in the context of non-pure OOPLs (such as 
Ada), you're probably right in suggesting it's worth distinguishing between 
single-fixed-variant (your "well-known") objects and more general ones. 
The additional flexibility gained in declaring an explicit derivable type 
is a waste of time if future variants are unlikely.

[Matt's example]

:An abstract data type wouldn't buy you very much except syntactic
:overhead.

Agree.

:Thinking in terms of packages (or "modules", if you prefer that term) is
:fundamental to Ada programming.  If you're using singleton instances of
:types everywhere, motivated perhaps by some notion of "purity," then
:that may be a sign that you're fighting the language.

:) :)

:In a typical Ada application, some abstractions are implemented as state
:machine packages, and some abstractions are implemented as instances of
:an abstract data type.  There is nothing odd or unnatural about this.

It's certainly idiomatic.


-- 
Don (Harrison).   donh at syd.csa.com.au






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

* Re: Can't export object of private type
  1999-03-02  0:00               ` fraser
@ 1999-03-03  0:00                 ` Don Harrison
  0 siblings, 0 replies; 128+ messages in thread
From: Don Harrison @ 1999-03-03  0:00 UTC (permalink / raw)


I nearly cried when nospam@thanks.com.au said:

(Oh, it's nothing personal (the tagline) btw, I'm just very sensitive
like that. ..

Well, it's distinctive anyway. :)

[..]

>I guess I was aware of implicit dereferencing. What I didn't appreciate 
>was the value of combining it with formal access-parameters.

Oh, yes indeedy woo.  The day it dawned on me that you could do that was
a good day. ..

[example]

How Ada's OO mechanisms are supposed to hang together hasn't completely 
gelled for me yet but some of the pieces have fallen into place. Thanks 
for your help.


-- 
Don (Harrison).   donh at syd.csa.com.au






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

* Re: Can't export object of private type
  1999-03-03  0:00               ` Can't export object of private type Don Harrison
@ 1999-03-03  0:00                 ` Don Harrison
  1999-03-03  0:00                   ` Nick Roberts
  1999-03-08  0:00                 ` Matthew Heaney
  1 sibling, 1 reply; 128+ messages in thread
From: Don Harrison @ 1999-03-03  0:00 UTC (permalink / raw)


I wrote:

:  type T_Type (<>) is abstract tagged private;

This should have been

:  type T_Type (<>) is abstract tagged limited private;
                                       ^^^^^^^

-- 
Don (Harrison).   donh at syd.csa.com.au






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

* Re: Can't export object of private type
  1999-03-01  0:00               ` robert_dewar
@ 1999-03-03  0:00                 ` Don Harrison
  1999-03-03  0:00                   ` robert_dewar
  0 siblings, 1 reply; 128+ messages in thread
From: Don Harrison @ 1999-03-03  0:00 UTC (permalink / raw)


Robert Dewar wrote:

:In article <F7wKy8.4Jq@syd.csa.com.au>,
:  nospam@thanks.com.au wrote:
:>   "A recursive declaration is one which is composed of at
:>    least  one declaration defined (transitively) in terms
:>    of the declaration being considered."
:
:This is not even close to a formal definition ..

Yes, it's an informal definition, but one that you ought to be able to 
comprehend. 

In any case, you haven't shown that non-linear elaboration is impossible.
However, I accept it would be complex due to Ada's ambitious elaboration 
capabilities (including the ability to call operations).

Linear elaboration may help reduce that complexity to an acceptable level.


-- 
Don (Harrison).   donh at syd.csa.com.au






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

* Re: Can't export object of private type
  1999-03-03  0:00                     ` Don Harrison
@ 1999-03-03  0:00                       ` Samuel Mize
  1999-03-04  0:00                         ` Don Harrison
  0 siblings, 1 reply; 128+ messages in thread
From: Samuel Mize @ 1999-03-03  0:00 UTC (permalink / raw)


Don Harrison <nospam@thanks.com.au> wrote:
> Matt Heaney wrote:

> :If you know up front how many "instances" of an abstraction you have
> :--what I call the "well-known objects" pattern-- then a state machine
> :package is probably the way to go.  
> 
> Partitioning objects into "well-known" and less-well-known :)  will always 
> be somewhat arbitrary.

Perhaps a clearer term would be "enumerable" if this kind of confusion is
going to occur.  It doesn't seem arbitrary to me that either you can list
all the objects up front, by their nature, like the planets -- or not.


>However, in the context of non-pure OOPLs (such as 
> Ada), you're probably right in suggesting it's worth distinguishing between 
> single-fixed-variant (your "well-known") objects and more general ones. 
> The additional flexibility gained in declaring an explicit derivable type 
> is a waste of time if future variants are unlikely.

Is it not a waste of time in an OOPL, or is it not possible to avoid
doing it in an OOPL?  (That sounds confrontational and I apologize, but
I can't think of a better way to phrase it.)


> :In a typical Ada application, some abstractions are implemented as state
> :machine packages, and some abstractions are implemented as instances of
> :an abstract data type.  There is nothing odd or unnatural about this.
> 
> It's certainly idiomatic.

Does you mean this to counter Matt's statement?  If a language forces you
to use just one or the other, you would, and that would be idiomatic too.

I'm not sure what you're trying to get across.

Best,
Sam Mize

-- 
Samuel Mize -- smize@imagin.net (home email) -- Team Ada
Fight Spam: see http://www.cauce.org/ \\\ Smert Spamonam




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

* Re: Can't export object of private type
  1999-03-01  0:00             ` Don Harrison
  1999-03-01  0:00               ` Matthew Heaney
  1999-03-01  0:00               ` Nick Roberts
@ 1999-03-03  0:00               ` Robert A Duff
  1999-03-04  0:00                 ` Don Harrison
  2 siblings, 1 reply; 128+ messages in thread
From: Robert A Duff @ 1999-03-03  0:00 UTC (permalink / raw)


nospam@thanks.com.au (Don Harrison) writes:

> Since Planet_Id is exported, anyone can declare an object of that type. 
> We want to ensure there is only a single instance shared by all clients.

If you want a package to have control over object allocation,
export a type with unknown discriminants.  Then clients can't
create objects.  The package itself is the only thing that can
create objects, and so it can place whatever restrictions it
likes, in your case, just one.

- Bob
-- 
Change robert to bob to get my real email address.  Sorry.




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

* Single Extension; Polymorphic Arrays
  1999-03-03  0:00                   ` Don Harrison
@ 1999-03-03  0:00                     ` Nick Roberts
  1999-03-03  0:00                       ` Nick Roberts
  0 siblings, 1 reply; 128+ messages in thread
From: Nick Roberts @ 1999-03-03  0:00 UTC (permalink / raw)


It dawns on me that Ada provides special syntax for singletons of two
particular kinds of types: tasks and protected objects.  Perhaps it would
not be too drastic to provide for singletons of tagged types?

Given a base type:

   type Pop_Star is [abstract] tagged ...;

with an operation such as:

   procedure Exploit (Star: in [out] Pop_Star; Creaming_Off: out Money) [is
abstract];

we might allow a 'single extension declaration':

   Elvis: [aliased] [constant] new Pop_Star with
      record
         ...
      end record;

or a 'single private extension declaration':

   Elvis: [aliased] [constant] new Pop_Star with private;

which would then have to be privately completed by a full single extension.

The object 'Elvis' would be of an anonymous tagged type.  It would not be
possible to derive from this anonymous type, because it could not be named.
The Tag attribute would be applicable to an object such as 'Elvis', but not
the Class attribute.  The 'in' operation would be applicable to such objects
(but probably not often used).

A 'single-object' parameter form could be used within subprogram
declarations:

   procedure Exploit (for [constant] Elvis; Creaming_Off: out Money);

The 'constant' would be required for an 'in' parameter, and omitted for an
'out', 'in out', or 'access' parameter.  These subprograms would be
primitive operations of the anonymous type of the object 'Elvis' (if
declared within the same package specification).

A totally separate, but also useful idea, it occurs to me, would be
'polymorphic arrays': arrays which have an indefinite component subtype.

Supposing we extended the Pop_Star hierarchy:

   type Singer is new Pop_Star with ...;
   type Violinist is new Pop_Star with ...;
   type Drummer is new Pop_Star with ...;
   type Guitarist is new Pop_Star with ...;

We could then use an array object declaration to create an array of objects
of different, but related, types:

   type Corr_Name is (Andrea, Sharon, Caroline, Jim);

   Corrs: [aliased] [constant] array (Corr_Name) of Pop_Star'Class (Singer,
Violinist, Drummer, Guitarist);

At the end of this declaration is a new piece of syntax: the 'polymorphic
array type association'.  This is like an aggregate (and allows named
associations like an aggregate), but only specifies types (which must all be
definite).  Once the types of the components of one of these arrays are set,
they cannot be changed (i.e. the array is permanently constrained).

Alternatively, an initialisation can be used specify the different types of
the components:

   Corrs: [aliased] [constant] array (Corr_Name) of Pop_Star'Class :=
      (Andrea => (Singer with ...), Sharon => (Violinist with ...), Caroline
=> (Drummer with ...), Jim => (Guitarist with ...));

This demonstrates a new form of array aggregate -- a 'polymorphic array
aggregate' -- that could never be legal in Ada at present.  As usual, an
initialisation could be used in addition to a type association, in which
case the types must all match.

A named polymorphic array type could be declared:

   type Pop_Group is array (Positive range <>) of [aliased] Pop_Star'Class;

and then objects of this type could be declared, e.g.:

   Spice_Girls: Pop_Group(1..4)(others => Singer);

   Metallica: Pop_Group :=
      (1 => (Singer with ...), 2|3 => (Guitarist with ...), 4 => (Drummer
with ...));

and the usual operations would then be available:

   Brian_Adams: Singer;

   Super_7: Pop_Group(1..7) := Spice_Girls(2..3) & Metallica & Brian_Adams;

Implementation of these types would be a cinch (probably just an array of
pointers plus a block of data), and they would be terrifically useful.  A
classic example is the 'sparse array' (one which has more holes in it than
you would care to waste memory on).  Another is the 'array of strings',
e.g.:

   Messages: constant array (1..100) of String :=
      (1 => "Error: you must put the milk in before the tea",
       2 => "Error: you must extend your little finger when holding the
cup",
       ...);

Doing the equivalent of this in Ada 95 is still a pain.

More ideas for Ada 200X?  (Yet more :-)

-------------------------------------
Nick Roberts
-------------------------------------








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

* Re: Single Extension; Polymorphic Arrays
  1999-03-03  0:00                     ` Single Extension; Polymorphic Arrays Nick Roberts
@ 1999-03-03  0:00                       ` Nick Roberts
  1999-03-08  0:00                         ` Matthew Heaney
  0 siblings, 1 reply; 128+ messages in thread
From: Nick Roberts @ 1999-03-03  0:00 UTC (permalink / raw)


I wrote in message <7bju1u$q23$1@plug.news.pipex.net>...
|It dawns on me that Ada provides special syntax for singletons of two
|particular kinds of types: tasks and protected objects.

Three types, of course: tasks, protected objects, and arrays.

-------------------------------------
Nick Roberts
-------------------------------------








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

* Re: Can't export object of private type
  1999-03-03  0:00                 ` Don Harrison
@ 1999-03-03  0:00                   ` Nick Roberts
  1999-03-04  0:00                     ` Don Harrison
  1999-03-08  0:00                     ` Can't export object of private type Matthew Heaney
  0 siblings, 2 replies; 128+ messages in thread
From: Nick Roberts @ 1999-03-03  0:00 UTC (permalink / raw)


Also, you need to remove the function Solo_T from package T (it does nothing
and won't compile), and move the declaration of Self from the private part
of package T.Child (where it doesn't need to be, and will cause an
unnecessary dependency) to the package's body.  The 'access' parameters in
the subprograms need only be 'in out' parameters; this is (pointedly!) a
case where access parameters serve no useful purpose (because the objects
are always going to be declared at library level).  Otherwise: perfect!

-------------------------------------
Nick Roberts
-------------------------------------








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

* Re: Can't export object of private type
  1999-03-03  0:00                 ` Don Harrison
@ 1999-03-03  0:00                   ` robert_dewar
  0 siblings, 0 replies; 128+ messages in thread
From: robert_dewar @ 1999-03-03  0:00 UTC (permalink / raw)


In article <F80B6B.29J@syd.csa.com.au>,
  nospam@thanks.com.au wrote:
> Yes, it's an informal definition, but one that you ought
> to be able to comprehend.

Sorry, I can comprehend the vague thought behind it, but
no, I can't comprehend the precise technical intention,
because I don't believe it is consistent, or can be made
consistent.

If I say I don't see anyway to define something, and you
offer a vague thought that you would like to see it defined
anyway, that does not help me complete the definition.

Yes, we know the general thought here, but the devil is
in the details, as the saying goes, and I see no way of
dealing with these details.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    




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

* Re: Can't export object of private type
  1999-03-02  0:00             ` Matthew Heaney
  1999-03-02  0:00               ` Tom Moran
@ 1999-03-03  0:00               ` Don Harrison
  1999-03-03  0:00                 ` Don Harrison
  1999-03-08  0:00                 ` Matthew Heaney
  1 sibling, 2 replies; 128+ messages in thread
From: Don Harrison @ 1999-03-03  0:00 UTC (permalink / raw)


Matt Heaney wrote:

[Matt's example]

Thanks. Your pattern for a hierarchy of singletons is exactly what I'm after. 
Here is my test program based on your solution:


package T is

  type T_Type (<>) is abstract tagged private;
  type Access_Class_T_Type is access all T_Type'Class;

  procedure Display (T: access T_Type) is abstract;
  function Solo_T return Access_Class_T_Type is abstract;

private
  type T_Type is abstract tagged null record;
end;


package T.Child is

  type T_Child_Type (<>) is new T_Type with private;
  type Access_Class_T_Child_Type is access all T_Child_Type'Class;

  procedure Display (TC: access T_Child_Type);
  function Solo_T return Access_Class_T_Child_Type;

private
  type T_Child_Type is new T_Type with null record;
  Self: aliased T_Child_Type;
end;

with Text_IO; use Text_IO;
package body T.Child is

  procedure Display (TC: access T_Child_Type) is
  begin
    Put_Line ("I am a T_Child object");
  end;

  function Solo_T return Access_Class_T_Child_Type is
  begin
    return Self'Access;
  end;

end;


package T.Other_Child is 
  ...  -- similar
end;

package body T.Other_Child is 
  ...  -- similar
end;


with T; use T;
with T.Child; use T.Child;
with T.Other_Child; use T.Other_Child;
procedure Use_T is

  type T_Index_Type is new Integer range 1 .. 2;
  type T_Array_Type is array (T_Index_Type) of Access_Class_T_Type;

  T_Array: T_Array_Type := (
    1 => T.Child.Solo_T.all'Access,          -- 1)
    2 => T.OTher_Child.Solo_T.all'Access);   -- 1)

begin
  for I in T_Array'Range loop
    Display (T_Array(I) );                   -- 2)
  end loop;
end;


1) Can this ugly stuff be avoided?
2) Dispatching call.


:We have used the features the language provides us to design a type
:hierarchy such that, the client must use the singleton instance(s).  He
:has no other choice in the matter, which is the intended effect.

That's what I'm after.


-- 
Don (Harrison).   donh at syd.csa.com.au






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

* Re: Can't export object of private type
  1999-03-04  0:00                       ` Nick Roberts
@ 1999-03-04  0:00                         ` robert_dewar
  1999-03-05  0:00                           ` Nick Roberts
  1999-03-05  0:00                         ` Robert A Duff
  1 sibling, 1 reply; 128+ messages in thread
From: robert_dewar @ 1999-03-04  0:00 UTC (permalink / raw)


In article <7bmgfd$2d3$3@plug.news.pipex.net>,
  "Nick Roberts" <Nick.Roberts@dial.pipex.com> wrote:
> However, the next question is: _why_ is it perfectly
> legal Ada?  It's (very nearly) gibberish.  At best, it
> simply announces that if we derive a type from
> Access_Class_T_Type, we might (if we fancy) be declaring
> a function which matches (and therefore overrides) the
> above.  It never enforces any kind of promise.  At worst,
> it's a confusing waste of space.  Weird.  Who
> wrote this funny language?  (Own up ;-)

Hint: any time you think something is "very nearly
gibberish", it probably means you are missing a point :-)

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    




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

* Re: Can't export object of private type
  1999-03-03  0:00               ` Robert A Duff
@ 1999-03-04  0:00                 ` Don Harrison
  1999-03-04  0:00                   ` Robert A Duff
  0 siblings, 1 reply; 128+ messages in thread
From: Don Harrison @ 1999-03-04  0:00 UTC (permalink / raw)


Bob Duff wrote:

:nospam@thanks.com.au (Don Harrison) writes:
:
:> Since Planet_Id is exported, anyone can declare an object of that type. 
:> We want to ensure there is only a single instance shared by all clients.
:
:If you want a package to have control over object allocation,
:export a type with unknown discriminants.  Then clients can't
:create objects.  The package itself is the only thing that can
:create objects, and so it can place whatever restrictions it
:likes, in your case, just one.

Do you mean like this:

package T is
  type T_Type (<>) is .. private;  -- no limited
  ..
end;


-- 
Don (Harrison).   donh at syd.csa.com.au






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

* Re: Can't export object of private type
  1999-03-03  0:00                       ` Samuel Mize
@ 1999-03-04  0:00                         ` Don Harrison
  0 siblings, 0 replies; 128+ messages in thread
From: Don Harrison @ 1999-03-04  0:00 UTC (permalink / raw)


Sam Mize wrote:

:Don Harrison <nospam@thanks.com.au> wrote:
:> Matt Heaney wrote:
:
:> :If you know up front how many "instances" of an abstraction you have
:> :--what I call the "well-known objects" pattern-- then a state machine
:> :package is probably the way to go.  
:> 
:> Partitioning objects into "well-known" and less-well-known :)  will always 
:> be somewhat arbitrary.
:
:Perhaps a clearer term would be "enumerable" if this kind of confusion is
:going to occur.  It doesn't seem arbitrary to me that either you can list
:all the objects up front, by their nature, like the planets -- or not.

I think you're right that this kind of abstraction usually is enumerable
but the property which suggests their implementation as a state machine is 
that their underlying behaviour is well-defined and isn't expected to change. 
This quality obviates the need for an explicit derivable type.

The problem, of course, is that you're relying on foresight in anticipating 
no future requirement for variants. We can forsee future needs to some extent 
but not perfectly. 


:>However, in the context of non-pure OOPLs (such as 
:> Ada), you're probably right in suggesting it's worth distinguishing between 
:> single-fixed-variant (your "well-known") objects and more general ones. 
:> The additional flexibility gained in declaring an explicit derivable type 
:> is a waste of time if future variants are unlikely.
:
:Is it not a waste of time in an OOPL, or is it not possible to avoid
:doing it in an OOPL?  (That sounds confrontational and I apologize, but
:I can't think of a better way to phrase it.)

A decent pure OOPL (such as Eiffel) will leave open the possibility of 
deriving variants. Eiffel doesn't give you a choice - every class can 
have heirs, although you can freeze particular primitive operations if 
you choose. The downside is a loss of execution speed - roughly 15% of 
dispatching calls aren't optimised to non-dispatching calls (Gnu Eiffel).


:> :In a typical Ada application, some abstractions are implemented as state
:> :machine packages, and some abstractions are implemented as instances of
:> :an abstract data type.  There is nothing odd or unnatural about this.
:> 
:> It's certainly idiomatic.
:
:Does you mean this to counter Matt's statement?  

No. I mean to agree that it's idiomatic - even if I disagree with the 
philosophy leading to the idiom. :)

Ada allows you to choose the degree of reusability for abstractions. Many 
Ada developers exercise that choice and choose lower reusability and that 
may be reasonable for abstractions that have little prospect of changing. 
I prefer to err on the side of more reusability .. which inevitably makes 
my code less idiomatic.

:If a language forces you
:to use just one or the other, you would, and that would be idiomatic too.

Certainly - for example, idiomatic Eiffel maximises derivability.

:I'm not sure what you're trying to get across.

Agreement with the expressed facts without disagreeing with the underlying 
philosophy that leads to them. :)


-- 
Don (Harrison).   donh at syd.csa.com.au






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

* Re: Can't export object of private type
  1999-03-03  0:00                   ` Nick Roberts
@ 1999-03-04  0:00                     ` Don Harrison
  1999-03-04  0:00                       ` fraser
                                         ` (2 more replies)
  1999-03-08  0:00                     ` Can't export object of private type Matthew Heaney
  1 sibling, 3 replies; 128+ messages in thread
From: Don Harrison @ 1999-03-04  0:00 UTC (permalink / raw)


Nick Roberts wrote:

:Also, you need to remove the function Solo_T from package T (it does nothing 

It exports a reference to the singleton.

: .. and won't compile), 

GNAT didn't have any trouble.

:and move the declaration of Self from the private part
:of package T.Child (where it doesn't need to be, and will cause an
:unnecessary dependency) to the package's body.  

An unnecessary dependency on what?

:The 'access' parameters in
:the subprograms need only be 'in out' parameters; this is (pointedly!) a
:case where access parameters serve no useful purpose..  

The access-parameters serve two useful purposes:

  - An access entity of any access type to T_Type'Class can be used 
    as an actual parameter.
  - That entity can't be corrupted because access-parameters are 
    in-mode.

: (because the objects
:are always going to be declared at library level).

:  type T_Array_Type is array (T_Index_Type) of Access_Class_T_Type;
:
:  T_Array: T_Array_Type := (
:    1 => T.Child.Solo_T.all'Access,          -- 1)
:    2 => T.OTher_Child.Solo_T.all'Access);   -- 1)

This is client - not library - code.


Otherwise: perfect!

Thanks! :)


-- 
Don (Harrison).   donh at syd.csa.com.au






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

* Re: Can't export object of private type
  1999-03-04  0:00                 ` Don Harrison
@ 1999-03-04  0:00                   ` Robert A Duff
  0 siblings, 0 replies; 128+ messages in thread
From: Robert A Duff @ 1999-03-04  0:00 UTC (permalink / raw)


nospam@thanks.com.au (Don Harrison) writes:

> Do you mean like this:
> 
> package T is
>   type T_Type (<>) is .. private;  -- no limited
>   ..
> end;

No.  I forgot to say it -- it should be limited also.
Sorry.  Apparently, others have pointed out the same
trick at length -- I should have just kept my mouth shut.

- Bob
-- 
Change robert to bob to get my real email address.  Sorry.




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

* Re: Can't export object of private type
  1999-03-04  0:00                     ` Don Harrison
  1999-03-04  0:00                       ` fraser
@ 1999-03-04  0:00                       ` Nick Roberts
  1999-03-08  0:00                         ` Matthew Heaney
  1999-03-09  0:00                         ` Don Harrison
  1999-03-04  0:00                       ` Nick Roberts
  2 siblings, 2 replies; 128+ messages in thread
From: Nick Roberts @ 1999-03-04  0:00 UTC (permalink / raw)


Don Harrison wrote ...
|Nick Roberts wrote:
|
|:Also, you need to remove the function Solo_T from package T (it does
nothing
|
|It exports a reference to the singleton.

It's definitiely unnecessary, and doesn't export anything (that needs to be
exported).  It is unnecessary.

|: .. and won't compile),
|
|GNAT didn't have any trouble.

I have to agree with this -- I've tried it myself.  I'm still trying to work
out why.  The whole thing also works perfectly well if you delete this
function declaration too (try it!).

|:and move the declaration of Self from the private part
|:of package T.Child (where it doesn't need to be, and will cause an
|:unnecessary dependency) to the package's body.
|
|An unnecessary dependency on what?


The idea is to move everything not to do with the 'public' face of your
singletons out of package specs and into the bodies.  This way, if you nned
to change anything about the implementation of these objects, it will only
cause recompilation of the package bodies: if you have to change anything in
the specs, this will (potentially) cause (the necessity of) recompilation of
the specs, the bodies AND all the clients which use the specs.  You
generally want to avoid this.

|:The 'access' parameters in
|:the subprograms need only be 'in out' parameters; this is (pointedly!) a
|:case where access parameters serve no useful purpose..
|
|The access-parameters serve two useful purposes:
|
|  - An access entity of any access type to T_Type'Class can be used
|    as an actual parameter.

It can still be used with 'in out' parameters, you just have to dereference
them explicitly (by adding '.all').  However, the 'access' form is therefore
slightly more convenient (so I have used these in my example below).  There
is otherwise no difference in this example.

|  - That entity can't be corrupted because access-parameters are
|    in-mode.

Wrong.  The access value itself can't be changed, but the entity it
references can.

|: (because the objects
|:are always going to be declared at library level).
|
|:  type T_Array_Type is array (T_Index_Type) of Access_Class_T_Type;
|:
|:  T_Array: T_Array_Type := (
|:    1 => T.Child.Solo_T.all'Access,          -- 1)
|:    2 => T.OTher_Child.Solo_T.all'Access);   -- 1)
|
|This is client - not library - code.


I think you misunderstand.  The singleton objects are always going to be
declared at library level (we can be sure of this precisely because we have
prevented clients from creating these objects).  Objects which hold access
values -- so long as they are of the access types we have provided (also
declared at at library level) -- don't matter.

|Otherwise: perfect!
|
|Thanks! :)


You're most welcome, but I think you're example may not actually have been
quite perfect :-(  However, I have provided a template example below which
is :-)  I hope ;-)  This shows no less than two levels of derivation, and
may seem a little 'overkill'.  However, it is in the nature of small
examples to do so: the structure provided here will provide insulation from
change, something of great value for real-life (big!) systems.

I'm still learning about this stuff myself, so I'm grateful to Don et al for
making me investigate these things.  (Corollary: nothing I say should be
taken as Gospel by anyone :-)

Incidentally, that I've cast my examples in terms of planets is purely
arbitrary.

|Don (Harrison).   donh at syd.csa.com.au


-------------------------------------
Nick Roberts
-------------------------------------


package Planetary is
   type Solar_Planet(<>) is abstract tagged limited private;
   procedure Put_Name (Planet: access Solar_Planet) is abstract;
   type Planet_Access is access all Solar_Planet'Class;
   --function The_Planet return Planet_Access is abstract;
private
   type Solar_Planet is abstract tagged limited
      record
         Base: String(1..11) := "The Planet ";
      end record;
end;



package Planetary.Mercury is
   type Planet_Mercury is abstract new Solar_Planet with private;
   type Mercury_Access is access all Planet_Mercury'Class;
   function The_Planet return Mercury_Access;
private
   type Planet_Mercury is abstract new Solar_Planet with
      record
         Extra: String(1..7) := "Mercury";
      end record;
end;



with Ada.Text_IO; use Ada.Text_IO;
with Ada.Exceptions; use Ada.Exceptions;

package body Planetary.Mercury is

   package Inner is

      type Mercury_Secrets is new Planet_Mercury with
         record
            Special: String(1..8) := " Innards";
         end record;

      procedure Put_Name (Planet: access Mercury_Secrets);

   end;

   package body Inner is

      procedure Put_Name (Planet: access Mercury_Secrets) is
      begin
         Put_Line (Planet.Base & Planet.Extra & Planet.Special);
      exception
         when E: others =>
            Put_Line("Exception raised in Mercury.Put_Name");
            Put(Exception_Information(E));
            New_Line;
            raise;
      end;

   end Inner;

   Internal: aliased Inner.Mercury_Secrets;

   function The_Planet return Mercury_Access is
   begin
      return Internal'Access;
   exception
      when E: others =>
         Put_Line("Exception raised in Mercury.The_Planet");
         Put(Exception_Information(E));
         New_Line;
         raise;
   end;

end;



with Ada.Text_IO; use Ada.Text_IO;
with Ada.Exceptions; use Ada.Exceptions;
with Ada.Tags; use Ada.Tags;

with Planetary.Mercury;

use Planetary;

procedure Main is
   P1: Planet_Access := Planet_Access(Mercury.The_Planet);
begin
   Put_Line("P1 tag = " & Expanded_Name(P1.all'Tag));
   Put_Name(P1); -- dispatching
exception
   when E: others =>
      Put_Line("Exception raised in Main");
      Put(Exception_Information(E));
      New_Line;
      raise;
end;








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

* Re: Can't export object of private type
  1999-03-04  0:00                     ` Don Harrison
  1999-03-04  0:00                       ` fraser
  1999-03-04  0:00                       ` Nick Roberts
@ 1999-03-04  0:00                       ` Nick Roberts
  1999-03-04  0:00                         ` robert_dewar
  1999-03-05  0:00                         ` Robert A Duff
  2 siblings, 2 replies; 128+ messages in thread
From: Nick Roberts @ 1999-03-04  0:00 UTC (permalink / raw)


Well, I've worked out why GNAT doesn't complain about the inclusion of:

   function Solo_T return Access_Class_T_Type is abstract;

It's perfectly legal Ada (q.v. RM95 3.9.3)!  (Surprise surprise :-)

However, the next question is: _why_ is it perfectly legal Ada?  It's (very
nearly) gibberish.  At best, it simply announces that if we derive a type
from Access_Class_T_Type, we might (if we fancy) be declaring a function
which matches (and therefore overrides) the above.  It never enforces any
kind of promise.  At worst, it's a confusing waste of space.  Weird.  Who
wrote this funny language?  (Own up ;-)

-------------------------------------
Nick Roberts
-------------------------------------








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

* Re: Can't export object of private type
  1999-03-04  0:00                     ` Don Harrison
@ 1999-03-04  0:00                       ` fraser
  1999-03-09  0:00                         ` Don Harrison
  1999-03-04  0:00                       ` Nick Roberts
  1999-03-04  0:00                       ` Nick Roberts
  2 siblings, 1 reply; 128+ messages in thread
From: fraser @ 1999-03-04  0:00 UTC (permalink / raw)


I nearly cried when nospam@thanks.com.au said:

>The access-parameters serve two useful purposes:
>
>  - An access entity of any access type to T_Type'Class can be used 
>    as an actual parameter.
>  - That entity can't be corrupted because access-parameters are 
>    in-mode.

Slight correction: access parameters are sort of like 'in' mode, but the
thing they access isn't.  I.e., you can't change where they access, but
you can modify that object being accessed.

It's times like this that I wish I had my RM handy.

Fraser.




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

* Re: Can't export object of private type
  1999-03-04  0:00                         ` robert_dewar
@ 1999-03-05  0:00                           ` Nick Roberts
  0 siblings, 0 replies; 128+ messages in thread
From: Nick Roberts @ 1999-03-05  0:00 UTC (permalink / raw)


robert_dewar@my-dejanews.com wrote in message
<7bn2fc$8ih$1@nnrp1.dejanews.com>...
[...]
|Hint: any time you think something is "very nearly
|gibberish", it probably means you are missing a point :-)


Of course; but, then, what _is_ the point, please?!

-------------------------------------
Nick Roberts
-------------------------------------







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

* Abstract Subprograms of Untagged Types
  1999-03-05  0:00                         ` Robert A Duff
@ 1999-03-05  0:00                           ` Nick Roberts
  1999-03-05  0:00                             ` robert_dewar
  1999-03-05  0:00                             ` Tucker Taft
  0 siblings, 2 replies; 128+ messages in thread
From: Nick Roberts @ 1999-03-05  0:00 UTC (permalink / raw)


Robert A Duff wrote in message ...
|"Nick Roberts" <Nick.Roberts@dial.pipex.com> writes:
[...]
|>    function Solo_T return Access_Class_T_Type is abstract;
[...]
|> However, the next question is: _why_ is it perfectly legal Ada?  It's
(very
|> nearly) gibberish.
[...]
|The language isn't usually in the business of forbidding useless things.
|Error-prone things, yes.
|
|I think AARM-3.9.3(3.d) addresses the above.


First, to quote the AARM section Bob referred to:

-        3.d   Reason:  We considered disallowing untagged types from having
-        abstract primitive subprograms.  However, we rejected that plan,
-        because it introduced some silly anomalies, and because such
-        subprograms are harmless (if not terribly useful).  For example:

-3.e         package P is
-               type Field_Size is range 0..100;
-               type T is abstract tagged null record;
-               procedure Print(X : in T; F : in Field_Size := 0) is
abstract;
-              . . .
-            package Q is
-               type My_Field_Size is new Field_Size;
-               -- implicit declaration of Print(X : T; F : My_Field_Size :=
0) \
-is abstract;
-            end Q;

-        3.f   It seemed silly to make the derivative of My_Field_Size
-        illegal, just because there was an implicitly declared abstract
-        subprogram that was not primitive on some tagged type.  Other rules
-        could be formulated to solve this problem, but the current ones
seem
-        like the simplest.

Well, just to be crystal clear, I was not seriously criticising this
decision, in my previous post.  I well appreciate the difficulty of making
these kinds of design decisions.

However, while the above 'addresses' the issue, it really resolve it.  I
think the example above can be solved at a stroke by making the rule that an
abstract subprogram is never a primitive operation of an untagged type (it's
legal, but never inherited by derivatives of untagged types).  I think there
needs to be a corollary rule that every abstract subprogram must have at
least one parameter or return type which is a tagged type.  No doubt some
further special rules would be needed.

I've also no doubt that the designers thought of introducing these rules
(alluded to in 3.f), but judged them to add too much complexity to be
worthwhile.  This was a judgement, and fair enough.  However, I disagree
with it, and I would like to see the restrictions introduced in the next
revision of Ada.

I think the reason why can be found in my previous post (in this thread):
users can mistakenly declare abstract subprograms which could actually serve
no useful purpose, but which are quietly accepted by the compiler.
Compilers could be expected to give a warning, but this is at the mercy of
compiler makers (GNAT 3.11p apparently doesn't give any warning, but perhaps
rightly so given the absence of an RM95 implementation recommendation to
that effect).  But, surely it would be better still to force all compilers
to reject such a confusing construct?

Of course compilers cannot be expected to stop programmers from doing silly
things, but they should give a warning (or error) when they can tell the
programmer has (almost certainly) done something silly.

-------------------------------------
Nick Roberts
-------------------------------------








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

* Re: Abstract Subprograms of Untagged Types
  1999-03-05  0:00                           ` Abstract Subprograms of Untagged Types Nick Roberts
@ 1999-03-05  0:00                             ` robert_dewar
  1999-03-05  0:00                             ` Tucker Taft
  1 sibling, 0 replies; 128+ messages in thread
From: robert_dewar @ 1999-03-05  0:00 UTC (permalink / raw)


In article <7bp8bk$flc$1@plug.news.pipex.net>,
  "Nick Roberts" <Nick.Roberts@dial.pipex.com> wrote:
> However, while the above 'addresses' the issue, it really
> resolve it.  I
> think the example above can be solved at a stroke by
> making the rule that an
> abstract subprogram is never a primitive operation of an
> untagged type

Now that *would* be a very annoying restriction indeed!

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    




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

* Re: Abstract Subprograms of Untagged Types
  1999-03-05  0:00                           ` Abstract Subprograms of Untagged Types Nick Roberts
  1999-03-05  0:00                             ` robert_dewar
@ 1999-03-05  0:00                             ` Tucker Taft
  1999-03-05  0:00                               ` Nick Roberts
  1999-03-06  0:00                               ` robert_dewar
  1 sibling, 2 replies; 128+ messages in thread
From: Tucker Taft @ 1999-03-05  0:00 UTC (permalink / raw)


Nick Roberts wrote:
> I think the example above can be solved at a stroke by making the rule that an
> abstract subprogram is never a primitive operation of an untagged type (it's
> legal, but never inherited by derivatives of untagged types).

One reason we allow abstract primitives of an untagged type
is because one way to *disable* a particular primitive
that is inherited is to override it with an abstract primitive.

For example, if you declare a numeric type like "Meters" then
you automatically get an (inappropriate) multiplication operation 
that goes Meters * Meters => Meters.  One use of abstract primitives
is to override this operation and thereby make it uncallable.

> ... This was a judgement, and fair enough.  However, I disagree
> with it, and I would like to see the restrictions introduced in the next
> revision of Ada.

At this point, this seems very unlikely, since someone may
be quite happily taking advantage of the ability to declare
abstract primitives of an untagged type.

> ... But, surely it would be better still to force all compilers
> to reject such a confusing construct?

I'm not sure I see what is the big deal.  It doesn't
seem to cause any harm, and it might be useful (as exemplified
above).

> ...
> things, but they should give a warning (or error) when they can tell the
> programmer has (almost certainly) done something silly.

Identifying things that are harmless but silly can be difficult
and is probably more trouble than it is worth in most cases.
Identifying things that are likely to cause a run-time error
seems much more valuable.

> -------------------------------------
> Nick Roberts
> -------------------------------------

-- 
-Tucker Taft   stt@averstar.com   http://www.averstar.com/~stt/
Technical Director, Distributed IT Solutions  (www.averstar.com/tools)
AverStar (formerly Intermetrics, Inc.)   Burlington, MA  USA




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

* Re: Abstract Subprograms of Untagged Types
  1999-03-05  0:00                             ` Tucker Taft
@ 1999-03-05  0:00                               ` Nick Roberts
  1999-03-06  0:00                               ` robert_dewar
  1 sibling, 0 replies; 128+ messages in thread
From: Nick Roberts @ 1999-03-05  0:00 UTC (permalink / raw)


Tucker Taft wrote in message <36E04AA7.4CB8F686@averstar.com>...
[...]
|One reason we allow abstract primitives of an untagged type
|is because one way to *disable* a particular primitive
|that is inherited is to override it with an abstract primitive.


Aha!

[...]
|> and I would like to see the restrictions introduced in the next
|> revision of Ada.
|
|At this point, this seems very unlikely, since someone may
|be quite happily taking advantage of the ability to declare
|abstract primitives of an untagged type.


Accepted.

[...]
|> things, but they should give a warning (or error) when they can tell the
|> programmer has (almost certainly) done something silly.
|
|Identifying things that are harmless but silly can be difficult
|and is probably more trouble than it is worth in most cases.
|Identifying things that are likely to cause a run-time error
|seems much more valuable.


I would agree that good warnings are often hard to encode, and that foolish
warnings are as annoying as negligent omissions of warnings.  I suspect that
it would be useful for a compiler to give a warning under some
circumstances, when an abstract subprogram is declared.  Do you disagree?

If not, would you be kind enough to suggest what situations would be
appropriate for a warning?  Possibly, for example, whenever the subprogram
has no tagged parameter or return type, and none of any of its parameter or
return types is derived from a type which has, as a primitive operation, a
matching subprogram which is not itself abstract.  Perhaps it might be
appropriate to include a recommendation of such warnings in a future
revision?

|-Tucker Taft   stt@averstar.com   http://www.averstar.com/~stt/
|Technical Director, Distributed IT Solutions  (www.averstar.com/tools)
|AverStar (formerly Intermetrics, Inc.)   Burlington, MA  USA

-------------------------------------
Nick Roberts
-------------------------------------









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

* Re: Can't export object of private type
  1999-03-04  0:00                       ` Nick Roberts
  1999-03-04  0:00                         ` robert_dewar
@ 1999-03-05  0:00                         ` Robert A Duff
  1999-03-05  0:00                           ` Abstract Subprograms of Untagged Types Nick Roberts
  1 sibling, 1 reply; 128+ messages in thread
From: Robert A Duff @ 1999-03-05  0:00 UTC (permalink / raw)


"Nick Roberts" <Nick.Roberts@dial.pipex.com> writes:

> Well, I've worked out why GNAT doesn't complain about the inclusion of:
> 
>    function Solo_T return Access_Class_T_Type is abstract;
> 
> It's perfectly legal Ada (q.v. RM95 3.9.3)!  (Surprise surprise :-)
> 
> However, the next question is: _why_ is it perfectly legal Ada?  It's (very
> nearly) gibberish.  At best, it simply announces that if we derive a type
> from Access_Class_T_Type, we might (if we fancy) be declaring a function
> which matches (and therefore overrides) the above.  It never enforces any
> kind of promise.  At worst, it's a confusing waste of space.  Weird.  Who
> wrote this funny language?  (Own up ;-)

The language isn't usually in the business of forbidding useless things.
Error-prone things, yes.

I think AARM-3.9.3(3.d) addresses the above.

- Bob
-- 
Change robert to bob to get my real email address.  Sorry.




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

* Re: Abstract Subprograms of Untagged Types
  1999-03-05  0:00                             ` Tucker Taft
  1999-03-05  0:00                               ` Nick Roberts
@ 1999-03-06  0:00                               ` robert_dewar
  1 sibling, 0 replies; 128+ messages in thread
From: robert_dewar @ 1999-03-06  0:00 UTC (permalink / raw)


In article <36E04AA7.4CB8F686@averstar.com>,
  Tucker Taft <stt@averstar.com> wrote:
> At this point, this seems very unlikely, since someone
> may be quite happily taking advantage of the ability to
> declare abstract primitives of an untagged type.

This is indeed a critical feature, and one that was
specifically discussed during the design. It is definitely
used and useful!

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    




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

* Re: Can't export object of private type
  1999-03-02  0:00                   ` Matthew Heaney
  1999-03-03  0:00                     ` Don Harrison
@ 1999-03-07  0:00                     ` Ehud Lamm
  1 sibling, 0 replies; 128+ messages in thread
From: Ehud Lamm @ 1999-03-07  0:00 UTC (permalink / raw)


On Tue, 2 Mar 1999, Matthew Heaney wrote:

> In a typical Adaapplication, some abstractions are implemented as state
> machine packages, and some abstractions are implemented as instances of
> an abstract data type.  There is nothing odd or unnatural about this.

Hear hear!

It may be noted that this differentiation between ADO and ADTs is one of
Ada's advantages when it comes to abstraction. 

Somehow this distinction is lost by most OOP practitioners - only to be
rediscovered as the singleton pattern.

Ehud Lamm     mslamm@pluto.mscc.huji.ac.il
http://www2.cybericites.com/e/ehud  <== START HERE
http://www2.cybercities.com/e/ehud/ada <== Ada and SE stuff





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

* Re: Single Extension; Polymorphic Arrays
  1999-03-03  0:00                       ` Nick Roberts
@ 1999-03-08  0:00                         ` Matthew Heaney
  1999-03-08  0:00                           ` Tucker Taft
  1999-03-08  0:00                           ` Nick Roberts
  0 siblings, 2 replies; 128+ messages in thread
From: Matthew Heaney @ 1999-03-08  0:00 UTC (permalink / raw)


"Nick Roberts" <Nick.Roberts@dial.pipex.com> writes:

> I wrote in message <7bju1u$q23$1@plug.news.pipex.net>...
> |It dawns on me that Ada provides special syntax for singletons of two
> |particular kinds of types: tasks and protected objects.
> 
> Three types, of course: tasks, protected objects, and arrays.


Yes, and this is a feature of the language that adds unnecessary
complexity.  You shouldn't be trying to duplicate it - you should be
trying to get rid of it.

You don't need singleton tasks, or protected objects, or arrays, because
you can use existing mechanism to do the job (ie declare a type, and
then declare one instance of the type).  








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

* Re: Can't export object of private type
  1999-03-03  0:00               ` Can't export object of private type Don Harrison
  1999-03-03  0:00                 ` Don Harrison
@ 1999-03-08  0:00                 ` Matthew Heaney
  1999-03-10  0:00                   ` Don Harrison
  1 sibling, 1 reply; 128+ messages in thread
From: Matthew Heaney @ 1999-03-08  0:00 UTC (permalink / raw)


nospam@thanks.com.au (Don Harrison) writes:

> Here is my test program based on your solution:
> 
> 
> package T is
> 
>   type T_Type (<>) is abstract tagged private;
>   type Access_Class_T_Type is access all T_Type'Class;
> 
>   procedure Display (T: access T_Type) is abstract;
>   function Solo_T return Access_Class_T_Type is abstract;

I don't understand why you declared function Solo_T as abstract.  It is
not a primitive type for T_Type.

Even if it weren't abstract, why do you need it there in the root
package?  All the (singleton) instances live in child packages.


> 
> package T.Child is
> 
>   type T_Child_Type (<>) is new T_Type with private;
>   type Access_Class_T_Child_Type is access all T_Child_Type'Class;
> 
>   procedure Display (TC: access T_Child_Type);
>   function Solo_T return Access_Class_T_Child_Type;

Why does Solo_T return a pointer to a class-wide type?  You want to have
a function that returns a pointer to the _specific_ type, because you're
pointing to an object of that type.

There's no need for dispatching, so return the specific type:

  type T_Child_Access is access all T_Child_Type;

  function Solo_T return T_Child_Access;


> with T; use T;
> with T.Child; use T.Child;
> with T.Other_Child; use T.Other_Child;
> procedure Use_T is
> 
>   type T_Index_Type is new Integer range 1 .. 2;
>   type T_Array_Type is array (T_Index_Type) of Access_Class_T_Type;
> 
>   T_Array: T_Array_Type := (
>     1 => T.Child.Solo_T.all'Access,          -- 1)
>     2 => T.OTher_Child.Solo_T.all'Access);   -- 1)
> 
> begin
>   for I in T_Array'Range loop
>     Display (T_Array(I) );                   -- 2)
>   end loop;
> end;
> 
> 
> 1) Can this ugly stuff be avoided?

Yes.

What you did here was to declare some data (an array of pointers to
singletons) outside of any object, and perform an operation on that data
(display each object).

This isn't in the spirit of the object-oriented paradigm, in which data
is encapsulated by an object, and you send the object a message to
operate in that data.  Your implementation is just the opposite, and the
symptom is "ugly stuff."

A better way to think of this problem is that you have a (singleton)
collection object containing (pointers to) all the singleton instances
in your type hierarchy.  This super-object has a passive iterator to let
you visit the items in the collection.

Now, here's where we get back to our state-machine paradigm: the
subsystem rooted at package T _is_ the collection object.

You'll want to have a passive iterator to visit the items, something
like this:


package T is

  type T_Type (<>) is abstract tagged limited private;

   ...

  generic
    procedure Process 
     (Item : access T_Type'Class;
      Done : in out Boolean);
  procedure For_Every_Item;

end T;


There is no more ugly stuff, because it's hidden behind the wall of the
subsystem.  To display all the singleton instances, just do this:

procedure Display_Item
  (Item : access T_Type'Class;
   Done : in out Boolean) is
begin
  Display (Item);  -- dispatches
end;

procedure Display_Items is
  For_Every_Item (Display_Item);

And so now you just call Display_Items.  You the client don't have the
array or even the loop.

So how we implement this?

What we do is declare a "register" operation in the private region of
the root package, so that it's visible to child packages, but not to
clients.

During its elaboration, each child package registers its singleton
instance with root package, which stores the pointer in an array inside
the body of the root package.  

Something like:

package T is

  pragma Elaborate_Body;

...
private

  procedure Register (Item : in T_Class_Access);

end T;


package body T is

  Max : constant := 20;  -- adjust during maintenance

  subtype Item_Array_Range is Positive range 1 .. Max;

  type Item_Array is 
    array (Item_Array_Range) of T_Class_Access;

  Items : Item_Array;

  Last : Natural := 0;

  procedure Register (Item : in T_Class_Access) is
  begin
    Last := Item_Array_Range'(Last + 1);
    Items (Last) := Item;
  end;

end T;


Each time Register is called, it increments the Last index, and inserts
the item into the array.  (You don't have to worry about synchronization
issues, because elaboration is linear.)

So the passive iterator would be implemented as:

procedure For_Every_Item is

  Done : Boolean := False;

begin

  for I in Positive range 1 .. Last loop
     Process (Items (I), Done);
     exit when Done;
  end loop;

end For_Every_Item;


Each child package would be implemented something like:

package body T.Child is

...
begin
  
  Register (Solo);  -- (may need type conversion)

end T.Child;


Be sure you use pragma Elaborate_Body everywhere.

The root package holds the collection of singletons, and the collection
itself gets populated (automatically) by calls from child packages.

The client then just visits members in the collection object, which here
happens to be implemented as a state machine.  No more ugliness.


> :We have used the features the language provides us to design a type
> :hierarchy such that, the client must use the singleton instance(s).  He
> :has no other choice in the matter, which is the intended effect.
> 
> That's what I'm after.

One of the "features the language provides us" is the package, a tool
for the organization of name-space.  If you insist on only using
objects-that-are-instances-of-a-type everywhere, you're limiting your
range of potential solutions, and "ugly stuff" results.

By using a package as a state machine, the ugly stuff is hidden.  Which
is the ultimate goal, really.

Use all the name-space management tools the language offers.














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

* Re: Can't export object of private type
  1999-03-03  0:00                   ` Nick Roberts
  1999-03-04  0:00                     ` Don Harrison
@ 1999-03-08  0:00                     ` Matthew Heaney
  1999-03-08  0:00                       ` Nick Roberts
  1 sibling, 1 reply; 128+ messages in thread
From: Matthew Heaney @ 1999-03-08  0:00 UTC (permalink / raw)


"Nick Roberts" <Nick.Roberts@dial.pipex.com> writes:

> Also, you need to remove the function Solo_T from package T (it does nothing
> and won't compile), and move the declaration of Self from the private part
> of package T.Child (where it doesn't need to be, and will cause an
> unnecessary dependency) to the package's body.  

I would probably declare the singleton in the package body too, not in
the private region of the spec.

> The 'access' parameters in the subprograms need only be 'in out'
> parameters; this is (pointedly!) a case where access parameters serve
> no useful purpose (because the objects are always going to be declared
> at library level).


No.  There is a legitimate reason for making the operations take access
parameters.

The reason is that, because this is a singleton abstraction, you must
refer the (one) instance indirectly, via a pointer.  But you don't want
to have to always deference a pointer every time you use the object, and
access parameters save you the trouble.

The solution you're advocating would require that clients always
dereference the pointer before invoking the operation:

  function Maze return Maze_Access;

  ... Get_Room (2, Of_Maze => Maze.all);


But if the primitive operation takes an access parameter, then no
explicit deference is necessary:

   ... Get_Room (2, Of_Maze => Maze);


Access parameters allow you to manipulate singleton instances of a type
using the same syntax as for non-singleton instances, which is exactly
what we want.

See my recent post in the ACM patterns archive, "Abstract Factory
Revisited," for a discussion of these issues.

<http://www.acm.org/archives/patterns.html>

As a matter of fact, I submitted that example specifically to address
the issues that came up during this thread here on CLA.












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

* Re: Can't export object of private type
  1999-03-04  0:00                       ` Nick Roberts
@ 1999-03-08  0:00                         ` Matthew Heaney
  1999-03-09  0:00                         ` Don Harrison
  1 sibling, 0 replies; 128+ messages in thread
From: Matthew Heaney @ 1999-03-08  0:00 UTC (permalink / raw)


"Nick Roberts" <Nick.Roberts@dial.pipex.com> writes:

> I'm still learning about this stuff myself, so I'm grateful to Don et al for
> making me investigate these things.  (Corollary: nothing I say should be
> taken as Gospel by anyone :-)


You may find it help to peruse recent examples in the ACM patterns
archive.

<http://www.acm.org/archives/patterns.html>





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

* Re: Single Extension; Polymorphic Arrays
  1999-03-08  0:00                         ` Matthew Heaney
@ 1999-03-08  0:00                           ` Tucker Taft
       [not found]                             ` <m3ogm40wav.fsf@mheaney.ni.net>
  1999-03-08  0:00                           ` Nick Roberts
  1 sibling, 1 reply; 128+ messages in thread
From: Tucker Taft @ 1999-03-08  0:00 UTC (permalink / raw)


Matthew Heaney (matthew_heaney@acm.org) wrote:

: You don't need singleton tasks, or protected objects, or arrays, because
: you can use existing mechanism to do the job (ie declare a type, and
: then declare one instance of the type).  

That's not quite true in the case of tasks and protected types.
Sometimes the singleton nature is critical to proper functioning.

For example, it is reasonable to use a singleton task or protected object
to manage all access to an external device or other resource (e.g.
a network).  If this were exported as a task or protected *type* then
there would be no protection against simultaneous access.

In fact, during the 9X design process we argued about whether allowing
singleton protected objects was an important feature, and the rationale
given above won the day.

On the other hand, "singleton" arrays are truly just a short-hand,
and I would agree that they add some complexity, primarily because
they are a special case.

--
-Tucker Taft   stt@averstar.com   http://www.averstar.com/~stt/
Technical Director, Distributed IT Solutions  (www.averstar.com/tools)
AverStar (formerly Intermetrics, Inc.)   Burlington, MA  USA




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

* Re: Single Extension; Polymorphic Arrays
  1999-03-08  0:00                         ` Matthew Heaney
  1999-03-08  0:00                           ` Tucker Taft
@ 1999-03-08  0:00                           ` Nick Roberts
  1 sibling, 0 replies; 128+ messages in thread
From: Nick Roberts @ 1999-03-08  0:00 UTC (permalink / raw)


Matthew Heaney wrote in message ...
[...]
|You don't need singleton tasks, or protected objects, or arrays, because
|you can use existing mechanism to do the job (ie declare a type, and
|then declare one instance of the type).

I would certainly agree with the general principle that a language design
should strive to provide the facilities it does in as simple and
'orthogonal' (fitting together neatly) a manner as possible, but I disagree
with you, quite strongly, on the specific recommendations you seem to be
making here.

I use (and recommend the use of to my clients) single tasks and arrays all
the time (and latterly single protected objects too), and I would consider
it a serious pain to have to declare one-time types for them.  Surely such
type declarations would be confusing, in making the reader feel that they
are intended to be used more than once?  At the least, they would add extra
bulk to the program for no gain (in my opinion).

So, I stand by my recommendation to introduce a new 'single record
extension' in the next revision of the Ada standard.  I think it is simple
to understand, and to implement (in terms of an anonymous type), it would
not disturb existing code, and it would not have to be used by any
programmer who didn't want to.  Personally, I think it would solve the
"singleton problem" quite neatly, and would be useful to a lot of people.

-------------------------------------
Nick Roberts
-------------------------------------








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

* Re: Can't export object of private type
  1999-03-08  0:00                     ` Can't export object of private type Matthew Heaney
@ 1999-03-08  0:00                       ` Nick Roberts
  0 siblings, 0 replies; 128+ messages in thread
From: Nick Roberts @ 1999-03-08  0:00 UTC (permalink / raw)


Spot on about the access parameters.

-------------------------------------
Nick Roberts
-------------------------------------








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

* Re: Single Extension; Polymorphic Arrays
       [not found]                             ` <m3ogm40wav.fsf@mheaney.ni.net>
  1999-03-08  0:00                               ` Nick Roberts
@ 1999-03-08  0:00                               ` Tucker Taft
  1999-03-08  0:00                                 ` dennison
  1999-03-09  0:00                                 ` Nick Roberts
  1 sibling, 2 replies; 128+ messages in thread
From: Tucker Taft @ 1999-03-08  0:00 UTC (permalink / raw)


Matthew Heaney wrote:
> 
> stt@houdini.camb.inmet.com (Tucker Taft) writes:
> 
> > For example, it is reasonable to use a singleton task or protected object
> > to manage all access to an external device or other resource (e.g.
> > a network).  If this were exported as a task or protected *type* then
> > there would be no protection against simultaneous access.
> 
> I was thinking that you'd declare the task type and one instance of that
> type together in a package body.

That wouldn't really address the problem, in my view.  You may want to
export the fact that the manager is a protected or task object, so timed
or conditional entry call syntax can be used.  Furthermore, even if it
is in a package body, to help the future reader/maintainer you would
have to say something like "only one instance of this type is allowed." 
Seems a bit kludgey.

Fundamentally, task and protected types and objects are special, because
they provide synchronization, and with synchronization, uniqueness makes
a big difference.

> ...
-- 
-Tucker Taft   stt@averstar.com   http://www.averstar.com/~stt/
Technical Director, Distributed IT Solutions  (www.averstar.com/tools)
AverStar (formerly Intermetrics, Inc.)   Burlington, MA  USA




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

* Re: Single Extension; Polymorphic Arrays
  1999-03-08  0:00                               ` Tucker Taft
@ 1999-03-08  0:00                                 ` dennison
  1999-03-09  0:00                                 ` Nick Roberts
  1 sibling, 0 replies; 128+ messages in thread
From: dennison @ 1999-03-08  0:00 UTC (permalink / raw)


In article <36E40BD9.2652469B@averstar.com>,
  Tucker Taft <stt@averstar.com> wrote:

> or conditional entry call syntax can be used.  Furthermore, even if it
> is in a package body, to help the future reader/maintainer you would
> have to say something like "only one instance of this type is allowed."
> Seems a bit kludgey.

Inadaquate as well. Someone trying to figure out why things don't seem to be
synchronizing right would be forced to scrutinize the entire scope (if its
declared in the spec, that's the entire codebase!) to see that everyone is
using the same task/protected object. Having that guaranteed with a singleton
is an immense help.


T.E.D.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    




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

* Re: Single Extension; Polymorphic Arrays
       [not found]                             ` <m3ogm40wav.fsf@mheaney.ni.net>
@ 1999-03-08  0:00                               ` Nick Roberts
  1999-03-08  0:00                               ` Tucker Taft
  1 sibling, 0 replies; 128+ messages in thread
From: Nick Roberts @ 1999-03-08  0:00 UTC (permalink / raw)


Nevertheless, I think I could give you numerous examples of an array
declaration -- particularly constant ones -- for which a separate type
declaration would have been just plain silly.  I will cite one example here.
In the implementation of Ada.Calendar (for my compiler :-) I have an array
which holds the number of days expired before the beginning of each month:

   DbM: constant array (Month_Number) of Year_Days := (0, 31, ...);

Surely, it simply wouldn't make sense to explicitly declare a type for this
array, would it?  Such a type would never need to be used anywhere else; I
have to admit, it would be likely to do no harm other than adding a little
clutter.  I suppose, at the end of the day, it is a subjective argument, but
personally I prefer to have the special case of array object declarations.

-------------------------------------
Nick Roberts
-------------------------------------

Matthew Heaney wrote in message ...
[...]
|> On the other hand, "singleton" arrays are truly just a short-hand,
|> and I would agree that they add some complexity, primarily because
|> they are a special case.
|
|This is really what I was complaining about.  I read in one of early Ada
|(83) papers (by Brian Wichmann?) that the reason this feature was
|included was to appease Fortran programmers switching to Ada.
|
|Its presence in the language complicates things for neophytes, because
|it makes you think that you can do this:
|
|  type RT is
|    record
|      O : array (1 .. 5) of Integer;
|    end record;
|
|which is of course illegal.  But it _looks_ like legal, eh?









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

* Re: Can't export object of private type
  1999-03-04  0:00                       ` Nick Roberts
  1999-03-08  0:00                         ` Matthew Heaney
@ 1999-03-09  0:00                         ` Don Harrison
  1999-03-09  0:00                           ` Matthew Heaney
  1 sibling, 1 reply; 128+ messages in thread
From: Don Harrison @ 1999-03-09  0:00 UTC (permalink / raw)


Nick Roberts wrote:

:Don Harrison wrote ...
:|Nick Roberts wrote:
:|
:|:Also, you need to remove the function Solo_T from package T (it does
:nothing
:|
:|It exports a reference to the singleton.
:
:It's definitiely unnecessary, and doesn't export anything (that needs to be
:exported).  It is unnecessary.

Yes, you're right. As the code stands, it isn't necessary. What I really 
want is an abstract primitive operation, not so much for polymorphism, but 
so that derivations are forced to supply an access function to their (private) 
variable "Self". This is a form of contract which derivations must meet.


:|: .. and won't compile),
:|
:|GNAT didn't have any trouble.
:
:I have to agree with this -- I've tried it myself.  I'm still trying to work
:out why.  The whole thing also works perfectly well if you delete this
:function declaration too (try it!).

You're right.


:|:and move the declaration of Self from the private part
:|:of package T.Child (where it doesn't need to be, and will cause an
:|:unnecessary dependency) to the package's body.
:|
:|An unnecessary dependency on what?
:
:
:The idea is to move everything not to do with the 'public' face of your
:singletons out of package specs and into the bodies.  This way, if you nned
:to change anything about the implementation of these objects, it will only
:cause recompilation of the package bodies: if you have to change anything in
:the specs, this will (potentially) cause (the necessity of) recompilation of
:the specs, the bodies AND all the clients which use the specs.  You
:generally want to avoid this.

Got you. There are two opposing needs here:

  b) On one hand, you want to decrease compilation dependencies, 
     as you suggest.

  a) On the other, it's convenient for all private declarations 
     to be in the one place (rather than being split between private 
     part of spec and body). This makes the mechanics of reading 
     code less arduous - declarations in the private part of the spec 
     and operations using them can be viewed separately in 2 windows. 
     However, if declarations are also placed in the body, the body 
     window must be scrolled constantly to view declarations.
     To eliminate scrolling, you would need 3 windows! - spec, body 
     declarations and body operations.


:|:The 'access' parameters in
:|:the subprograms need only be 'in out' parameters; this is (pointedly!) a
:|:case where access parameters serve no useful purpose..

Matt has addressed this issue, so I won't cover it, except for..

:|  - That entity can't be corrupted because access-parameters are
:|    in-mode.
:
:Wrong.  The access value itself can't be changed, but the entity it
:references can.

You misunderstand. By "entity", I meant the reference.


:|: [this is .. a case where access parameters serve no useful purpose] 
:|:(because the objects are always going to be declared at library level).

Matt seems to have covered this (so I won't).

: .. However, I have provided a template example below which
:is :-)  I hope ;-)  This shows no less than two levels of derivation, and
:may seem a little 'overkill'.  

[your example]

Just wondering.. Would private child packages have been a better 
alternative to nested packages? [I have a pathological aversion to nested 
packages.]


-- 
Don (Harrison).   donh at syd.csa.com.au






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

* Re: Can't export object of private type
  1999-03-04  0:00                       ` fraser
@ 1999-03-09  0:00                         ` Don Harrison
  0 siblings, 0 replies; 128+ messages in thread
From: Don Harrison @ 1999-03-09  0:00 UTC (permalink / raw)


I nearly cried when Fraser wrote:

:I nearly cried when nospam@thanks.com.au said:
:
:>The access-parameters serve two useful purposes:
:>
:>  - An access entity of any access type to T_Type'Class can be used 
:>    as an actual parameter.
:>  - That entity can't be corrupted because access-parameters are 
:>    in-mode.
:
:Slight correction: access parameters are sort of like 'in' mode, but the
:thing they access isn't.  I.e., you can't change where they access, but
:you can modify that object being accessed.

Agree. Sorry if I wasn't clear.


-- 
Don (Harrison).   donh at syd.csa.com.au






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

* Re: Can't export object of private type
  1999-03-09  0:00                         ` Don Harrison
@ 1999-03-09  0:00                           ` Matthew Heaney
  1999-03-09  0:00                             ` Nick Roberts
  1999-03-10  0:00                             ` Don Harrison
  0 siblings, 2 replies; 128+ messages in thread
From: Matthew Heaney @ 1999-03-09  0:00 UTC (permalink / raw)


nospam@thanks.com.au (Don Harrison) writes:

> Nick Roberts wrote:
> 
> :|:Also, you need to remove the function Solo_T from package T (it does
> :nothing
>
> Yes, you're right. As the code stands, it isn't necessary. What I
> really want is an abstract primitive operation, not so much for
> polymorphism, but so that derivations are forced to supply an access
> function to their (private) variable "Self". This is a form of
> contract which derivations must meet.

You can't enforce this using the type system.

This is like declaring a type, and then trying to have an operation that
forces clients to declare instances of the type.  Huh???

There is a very practical reason why you'll need an accessor function:
no one will be able to use your singleton if you don't provide one!


> :|:and move the declaration of Self from the private part
> :|:of package T.Child (where it doesn't need to be, and will cause an
> :|:unnecessary dependency) to the package's body.
>
> Got you. There are two opposing needs here:
> 
>   a) On the other, it's convenient for all private declarations 
>      to be in the one place (rather than being split between private 
>      part of spec and body)....

I would declare the instance in the body.  The reason is that there
might be other abstractions that are needed by the instance.  

If you declare the instance in the spec, then you'll have to move those
with's into the spec too, which can cause unnecessary recompilations.

> Just wondering.. Would private child packages have been a better 
> alternative to nested packages? [I have a pathological aversion to nested 
> packages.]

If you have a choice between a child and a nested package, then use a
child.  The reason, of course, is to push module dependencies into the
child.  By moving the dependency to a child, you only have to recompile
the subtree, if that module changes.

This motivated by package design in my "Abstract Factory Revisited"
article in the ACM patterns archive.  

<http://www.acm.org/archives/patterns.html>

Maze_Type has a dependency on Maze_Room, because one of its operations
takes a room as a return value:


  type Maze_Type (<>) is limited private;

  function Get_Room 
    (Number  : in     Positive;
     Of_Maze : access Maze_Type) return Room_Handle;

In the original version, I had this:

package Mazes is

  type Maze_Type (<>) is limited private;

...
  type Maze_Room is new Maze_Item with private;

  <room ops>

  function Get_Room (Number : ...


With this organization of types, then the entire subsystem (rooted at
Mazes) has a dependency on Maze_Type, Maze_Item, and Maze_Room.  If any
of those types changes (say, because you need to add an operation), then
every package in the subsystem must get recompiled.

I reasoned that the only type that really needs to go in the root spec
is Maze_Item, because that's the root type for all the things you put in
a maze game (walls, doors, and rooms all derive from that type).

But no one depends Maze_Type except the client.  So I moved that type
into a child package, which allowed me to move the declaration of the
room type into a child package.  Like this:

package Mazes.Rooms is

  type Maze_Room is new Maze_Item with private;

...
end Mazes.Rooms;


with Mazes.Rooms;
package Mazes.Games is

  type Maze_Type (<>) is limited private;

  function Get_Room 
    (Number  : in     Positive;
     Of_Maze : access Maze_Type) return Rooms.Room_Handle;

...
end Mazes.Games;


Now, with this improved organization, if Maze_Room type changes, then
only clients of that one package (like Mazes.Games) need to be
recompiled.

If Maze_Type changes, then only clients of that package need to be
recompiled.

The rest of the children of package Mazes are oblivious to changes in
Maze_Room or Maze_Type, because they no longer depend on those types.

In Ada especially, you always have to be thinking about how to remove
module dependencies.  Indeed, the child package facility was created
_expressly_ to allow you to remove dependencies, by moving the
dependency to a subtree.  

There is an analogy to deep type hierarchies.  The higher in the
hierarchy you make a change, the more clients have to get recompiled.
This problem is so pernicious and so common it has a name: the "fragile
base class" problem.

In Ada, you have a similar problem for modules.  Change the root module
in a subsystem, and _every_ module in the subsystem has to get
recompiled.

You cannot just be thinking of programming in the abstract.  You must
also be thinking about the actual construction of systems.  Frequent
recompilations will do you in, and you must take active steps to avoid
it.  

That means careful module design is required.  Move module dependencies
to a body whenever possible, and push spec dependencies downward in the
package hierarchy.

In my example above, two types were moved moved from a parent package to
two children.  This protects other children in that hierarchy from
changes in those types.

This is one of the reasons I prefer to declare singleton abstractions as
state machine packages whenever possible, because the "representation"
of that "object" can stay in the body.  

To use a type means you have to implement the type in the private region
of the spec, which means the entities you need to implement that type
have to get with'd by the spec.  

Change one of those other packages, and every package that with's yours
will have to be recompiled.  This would not be true if those
dependencies were moved into the body.

This is basically why always say, Don't implement a singleton as a type,
unless you have a compelling need to.  It just creates module
dependencies that wouldn't be there otherwise.

'nuff said,
Matt





























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

* Re: Single Extension; Polymorphic Arrays
  1999-03-08  0:00                               ` Tucker Taft
  1999-03-08  0:00                                 ` dennison
@ 1999-03-09  0:00                                 ` Nick Roberts
  1 sibling, 0 replies; 128+ messages in thread
From: Nick Roberts @ 1999-03-09  0:00 UTC (permalink / raw)


Tucker Taft wrote in message <36E40BD9.2652469B@averstar.com>...
[...]
|Fundamentally, task and protected types and objects are special, because
|they provide synchronization, and with synchronization, uniqueness makes
|a big difference.
[...]
|-Tucker Taft   stt@averstar.com   http://www.averstar.com/~stt/
|Technical Director, Distributed IT Solutions  (www.averstar.com/tools)
|AverStar (formerly Intermetrics, Inc.)   Burlington, MA  USA

And so, by extrapolation, I would argue that a single record extension
declaration needs to be provided, because the (overriding) implementations
of these objects may involve the need to enforce the singleness of
interaction with other entities (including situations where synchronisation
issues are important).

It seems to me, therefore, that the necessity (or at least usefulness) of
being able to prevent the creation of further copies of an object of an
extended type is the same as for task and protected objects.

(NB: I reiterate my understanding of how immensely difficult is the task of
a designing a programming language.)

-------------------------------------
Nick Roberts
-------------------------------------








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

* Re: Can't export object of private type
  1999-03-09  0:00                           ` Matthew Heaney
@ 1999-03-09  0:00                             ` Nick Roberts
  1999-03-10  0:00                             ` Don Harrison
  1 sibling, 0 replies; 128+ messages in thread
From: Nick Roberts @ 1999-03-09  0:00 UTC (permalink / raw)


Matthew Heaney wrote in message ...
[...]
|> Just wondering.. Would private child packages have been a better
|> alternative to nested packages? [I have a pathological aversion to nested
|> packages.]
|
|If you have a choice between a child and a nested package, then use a
|child.  The reason, of course, is to push module dependencies into the
|child.  By moving the dependency to a child, you only have to recompile
|the subtree, if that module changes.


In fact, in the planetary example I gave, the inner nested package was
unnecessary (I simply fell foul of a GNAT 3.11p bug, which causes the need
for a declaration of an overriding abstract subprogram before the body of
the subprogram*).

It may be advantageous to use child packages, under some (unlikely)
circumstances.

[...]
|This is basically why always say, Don't implement a singleton as a type,
|unless you have a compelling need to.  It just creates module
|dependencies that wouldn't be there otherwise.


I would personally agree with this injunction, in general.  In Ada, it
produces a simpler result, except for the polymorphism, which can be
simulated as required by a big 'case' statement (as I demonstrated in an
earlier example).  Of course, this is slightly kludgeous, and may, in some
(perhaps many) cases, be so onerous as to make the type-based solution
preferable.

There is, however, another kind of situation that the package-based approach
does not solve.  This is where a base type (with its promised operations)
already exists, and cannot be (or is not to be) revoked (e.g. because it is
already used elsewhere, or because there will be some non-singleton types
derived from it).  The best solution to this situation is (unfortunately)
the introduction of the 'single record extension' object declaration to the
language (which I would hope could be done at the next revision, barring a
better alternative or a crushing objection).

-------------------------------------
Nick Roberts
-------------------------------------

* this bug will be fixed in version 3.12








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

* Re: Can't export object of private type
  1999-03-10  0:00                         ` Robert A Duff
  1999-03-10  0:00                           ` dennison
@ 1999-03-10  0:00                           ` robert_dewar
  1 sibling, 0 replies; 128+ messages in thread
From: robert_dewar @ 1999-03-10  0:00 UTC (permalink / raw)


In article <wccn21lyzsl.fsf@world.std.com>,
  Robert A Duff <bobduff@world.std.com> wrote:
> dennison@telepath.com writes:
>
> > procedure Main is
> > begin
> >    null;  -- The with's do all the work
> > end;
> >
> > I've seen it done. The problem is that any tasks that
> > have terminate options will immediately complete. ...

If your compiler does this it is (very significantly)
broken! Clearly the semantics of Ada do not allow this
premature termination.


-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    




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

* Re: Can't export object of private type
  1999-03-10  0:00                           ` dennison
@ 1999-03-10  0:00                             ` robert_dewar
  1999-03-10  0:00                               ` dennison
  0 siblings, 1 reply; 128+ messages in thread
From: robert_dewar @ 1999-03-10  0:00 UTC (permalink / raw)


In article <7c6bqr$2jb$1@nnrp1.dejanews.com>,
  dennison@telepath.com wrote:
> Oh really?  How does that work? How does such a program
> get compiled or invoked?

Ask your friendly implementor, these questions are
obviously not ones that get answered by the RM!

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    




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

* Re: Can't export object of private type
  1999-03-10  0:00                             ` robert_dewar
@ 1999-03-10  0:00                               ` dennison
  1999-03-11  0:00                                 ` dennison
                                                   ` (2 more replies)
  0 siblings, 3 replies; 128+ messages in thread
From: dennison @ 1999-03-10  0:00 UTC (permalink / raw)


In article <7c6qek$gcm$1@nnrp1.dejanews.com>,
  robert_dewar@my-dejanews.com wrote:
> In article <7c6bqr$2jb$1@nnrp1.dejanews.com>,
>   dennison@telepath.com wrote:
> > Oh really?  How does that work? How does such a program
> > get compiled or invoked?
>
> Ask your friendly implementor, these questions are
> obviously not ones that get answered by the RM!

OK, how does this get implemented? I read the Aonix and GreenHills manuals
fairly thouroughly, and don't remember comming across this. I don't remember
seeing it in the super-secret gnat documentation either, but I'll go look now.

T.E.D.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    




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

* Re: Can't export object of private type
  1999-03-10  0:00                         ` Robert A Duff
@ 1999-03-10  0:00                           ` dennison
  1999-03-11  0:00                             ` dennison
  1999-03-10  0:00                           ` robert_dewar
  1 sibling, 1 reply; 128+ messages in thread
From: dennison @ 1999-03-10  0:00 UTC (permalink / raw)


In article <wccn21lyzsl.fsf@world.std.com>,
  Robert A Duff <bobduff@world.std.com> wrote:
> dennison@telepath.com writes:
>
> > procedure Main is
> > begin
> >    null;  -- The with's do all the work
> > end;
> >
> > I've seen it done. The problem is that any tasks that have terminate options
> > will immediately complete. ...
>
> No, that's not right.  Such tasks will not complete until all the other
> tasks are done.

Its been a while, but in Ada83 the way I remember it I would see any task that
was a child of the main unit go to a "completed" state when the main unit
completed and the task hit a terminate option, if it had no subtasks still
running. Of course the program itself won't complete until all other tasks
complete, but that didn't stop any one task from quitting.

T.E.D.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    




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

* Re: Can't export object of private type
  1999-03-08  0:00                 ` Matthew Heaney
@ 1999-03-10  0:00                   ` Don Harrison
  1999-03-10  0:00                     ` Matthew Heaney
  0 siblings, 1 reply; 128+ messages in thread
From: Don Harrison @ 1999-03-10  0:00 UTC (permalink / raw)


Matt Heaney wrote:

:nospam@thanks.com.au (Don Harrison) writes:

:>   function Solo_T return Access_Class_T_Type is abstract;
:
:I don't understand why you declared function Solo_T as abstract.  It is
:not a primitive type for T_Type.
:
:Even if it weren't abstract, why do you need it there in the root
:package?  All the (singleton) instances live in child packages.

See my response to Nick.


:>   type Access_Class_T_Child_Type is access all T_Child_Type'Class;
:> 
:>   function Solo_T return Access_Class_T_Child_Type;
:
:Why does Solo_T return a pointer to a class-wide type?  You want to have
:a function that returns a pointer to the _specific_ type, because you're
:pointing to an object of that type.

You're probably right.


:There's no need for dispatching, so return the specific type:
:
:  type T_Child_Access is access all T_Child_Type;
:
:  function Solo_T return T_Child_Access;

Perhaps not. But, there *is* a need to force derivations to provide an 
access function ..which apparently Ada can't give us.


:>   type T_Index_Type is new Integer range 1 .. 2;
:>   type T_Array_Type is array (T_Index_Type) of Access_Class_T_Type;
:> 
:>   T_Array: T_Array_Type := (
:>     1 => T.Child.Solo_T.all'Access,          -- 1)
:>     2 => T.OTher_Child.Solo_T.all'Access);   -- 1)

:> 1) Can this ugly stuff be avoided?
:
:Yes.
:
:What you did here was to declare some data (an array of pointers to
:singletons) outside of any object, and perform an operation on that data
:(display each object).
:
:This isn't in the spirit of the object-oriented paradigm, in which data
:is encapsulated by an object, and you send the object a message to
:operate in that data.  Your implementation is just the opposite, and the
:symptom is "ugly stuff."

Small nit.. The OO paradigm says nothing about sending messages. Although 
many people use this terminology (from dynamically-typed OOPLs), it's 
better to speak of dispatching calls in the context of statically-typed 
OOPLs.

The use of the main program as a client has more to do with a desire to 
simplify the example while satisfying Ada's requirement for a main program 
than indicating a design preference on my part. 

The "ugly stuff" is not the result of lax design.

It's caused by the fact that Ada requires explicit syntax to represent 
the notions of class membership ("'Class") and referencing ("access").
In many OOPLs, these details are implicit rather than explicit, thus 
relieving the developer from having to represent them explicitly. 
Ada has always had a literal approach to typing syntax and semantics and 
this philosophy has been preserved in its OO typing. Hence, explicit syntax 
is used to distinguish between:

  - Objects and references to them.
  - Specific and classwide types.

You can hide that syntax from clients, as you suggest, but that isn't 
the same as removing it.


:A better way to think of this problem is that you have a (singleton)
:collection object containing (pointers to) all the singleton instances
:in your type hierarchy. ..

Agree.


:Now, here's where we get back to our state-machine paradigm: the
:subsystem rooted at package T _is_ the collection object.

This would be the wrong way to model it, IMO. An object and a collection 
of them should be separate abstractions.


:  pragma Elaborate_Body;

This is a welcome addition to Ada. It gives what the default semantics 
should have been from the beginning. 


:Each time Register is called, it increments the Last index, and inserts
:the item into the array.  (You don't have to worry about synchronization
:issues, because elaboration is linear.)

Right.


-- 
Don (Harrison).   donh at syd.csa.com.au






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

* Re: Can't export object of private type
  1999-03-09  0:00                           ` Matthew Heaney
  1999-03-09  0:00                             ` Nick Roberts
@ 1999-03-10  0:00                             ` Don Harrison
  1999-03-10  0:00                               ` Matthew Heaney
  1 sibling, 1 reply; 128+ messages in thread
From: Don Harrison @ 1999-03-10  0:00 UTC (permalink / raw)


Matt Heaney wrote:

:nospam@thanks.com.au (Don Harrison) writes:

:> .. What I
:> really want is an abstract primitive operation, not so much for
:> polymorphism, but so that derivations are forced to supply an access
:> function to their (private) variable "Self". This is a form of
:> contract which derivations must meet.
:
:You can't enforce this using the type system.

I'm beginning to believe that. :(

:This is like declaring a type, and then trying to have an operation that
:forces clients to declare instances of the type.  Huh???

Not at all. It's nothing like that. The nature of the inheritance relation 
is completely different from the client relation. Whereas a client should 
*optionally* use a supplier (including declaring instances of it), a 
derivation should be *forced* to honour its parent's contract; otherwise, 
polymorphism breaks. 


:> Got you. There are two opposing needs here:
:> 
:>   a) On the other, it's convenient for all private declarations 
:>      to be in the one place (rather than being split between private 
:>      part of spec and body)....
:
:I would declare the instance in the body.  The reason is that there
:might be other abstractions that are needed by the instance.  
:
:If you declare the instance in the spec, then you'll have to move those
:with's into the spec too, which can cause unnecessary recompilations.

Sure. 


-- 
Don (Harrison).   donh at syd.csa.com.au






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

* Re: Can't export object of private type
  1999-03-10  0:00                   ` Don Harrison
@ 1999-03-10  0:00                     ` Matthew Heaney
  1999-03-10  0:00                       ` dennison
  0 siblings, 1 reply; 128+ messages in thread
From: Matthew Heaney @ 1999-03-10  0:00 UTC (permalink / raw)


nospam@thanks.com.au (Don Harrison) writes:

> :There's no need for dispatching, so return the specific type:
> :
> :  type T_Child_Access is access all T_Child_Type;
> :
> :  function Solo_T return T_Child_Access;
> 
> Perhaps not. But, there *is* a need to force derivations to provide an 
> access function ..which apparently Ada can't give us.

If you need to compute the product of X and Y, there's nothing in the
language that forces you to write the expression X * Y either!


> The use of the main program as a client has more to do with a desire to 
> simplify the example while satisfying Ada's requirement for a main program 
> than indicating a design preference on my part. 

There is no requirement for a main program in Ada95.  (Although I must
admit I've never actually tried to write an Ada95 without one.)


> The "ugly stuff" is not the result of lax design.

It is the result of failing to encapsulate low-level data (an array)
behind a higher-level abstraction (a collection with iterator).

It is the same as if you had written

  type Integer_Stack is   
    record
       Items : Integer_Array;    -- can this ugly stuff be omitted?
       Top   : Natural := 0;
    end record;

Yes, of course the ugliness can be omitted -- by hiding it.

 
> It's caused by the fact that Ada requires explicit syntax to represent 
> the notions of class membership ("'Class") and referencing ("access").

No.  You declared a collection object as an unencapsulated array, and
then complained that it was ugly.  (And I agree with you.)

The language gives you tools to remove the ugliness, by hiding it behind
an abstraction (in this case, a collection abstraction implemented as a
state machine).


> You can hide that syntax from clients, as you suggest, but that isn't 
> the same as removing it.

No one is saying you can eliminate the array; there has to be an array
somewhere.  All I'm advocating is that you declare the array in the
package body, and visit the items in that array via an iterator.

I'm viewing the array at a higher level of abstraction.  I'm saying that
what you have is a collection of singletons, which happens to be
implemented as an array.  The array is strictly an implementation
detail, that we both agree is ugly.






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

* Re: Can't export object of private type
  1999-03-10  0:00                             ` Don Harrison
@ 1999-03-10  0:00                               ` Matthew Heaney
  0 siblings, 0 replies; 128+ messages in thread
From: Matthew Heaney @ 1999-03-10  0:00 UTC (permalink / raw)


nospam@thanks.com.au (Don Harrison) writes:

> :You can't enforce this using the type system.
> 
> I'm beginning to believe that. :(

The language can't do everything for you.  If you declare a type like
this:

package P is

   type T (<>) is limited private;

   <ops for T>

end P;


then there's nothing in the language that forces you to implement a
constructor for the type.  This type is useless without a constructor,
but Ada can only prevent you from doing harmful things, not useless
things.

And besides, you don't need the language to tell you, because human
programmers who try to use your type will tell you right away!

 
> :This is like declaring a type, and then trying to have an operation that
> :forces clients to declare instances of the type.  Huh???
> 
> Not at all. It's nothing like that. The nature of the inheritance relation 
> is completely different from the client relation. Whereas a client should 
> *optionally* use a supplier (including declaring instances of it), a 
> derivation should be *forced* to honour its parent's contract; otherwise, 
> polymorphism breaks. 
 
I see it exactly the opposite.  Construction is part of the relationship
between client and specific type, not part of the inheritance relation.

Different clients have different construction needs, and every client
might very well declare his own custom constructor for the type.  This
is the great thing about child units:

package P is 

  type T (<>) is limited private;

...       
  function Default_Constructor return T_Access;

end P;

Let's say I have very specific construction needs, and
Default_Constructor isn't adequate.  For ex, I might need to stream the
object in off of disk.  So I just declare my own constructor:

function P.My_Constructor (Filename : String) return T_Access;

One of the purposes of the child facility is to allow you to efficiently
extend an abstraction.  Note that this kind of "extension" doesn't
extend the type in the same sense as deriving from a tagged type.  

We are not creating a new type.  Here, we want only to add a
non-primitive operation to the type --a constructor-- that has the same
efficiency and convenience of primitive operations.




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

* Re: Can't export object of private type
  1999-03-10  0:00                     ` Matthew Heaney
@ 1999-03-10  0:00                       ` dennison
  1999-03-10  0:00                         ` Robert A Duff
  1999-03-10  0:00                         ` robert_dewar
  0 siblings, 2 replies; 128+ messages in thread
From: dennison @ 1999-03-10  0:00 UTC (permalink / raw)


In article <m3yal5vkt5.fsf@mheaney.ni.net>,
  Matthew Heaney <matthew_heaney@acm.org> wrote:

> There is no requirement for a main program in Ada95.  (Although I must
> admit I've never actually tried to write an Ada95 without one.)

If you mean:

procedure Main is
begin
   null;  -- The with's do all the work
end;

I've seen it done. The problem is that any tasks that have terminate options
will immediately complete. Since you don't really know what tasks you get
when you with in a package, this can produce some bizzare results. For that
reason alone I like to try to find something for the main routine to do.
Often its not possible to give it a non-terminating chore, though.


T.E.D.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    




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

* Re: Can't export object of private type
  1999-03-10  0:00                       ` dennison
  1999-03-10  0:00                         ` Robert A Duff
@ 1999-03-10  0:00                         ` robert_dewar
  1999-03-10  0:00                           ` dennison
  1999-03-11  0:00                           ` Don Harrison
  1 sibling, 2 replies; 128+ messages in thread
From: robert_dewar @ 1999-03-10  0:00 UTC (permalink / raw)


In article <7c6566$rps$1@nnrp1.dejanews.com>,
  dennison@telepath.com wrote:
> If you mean:
>
> procedure Main is
> begin
>    null;  -- The with's do all the work
> end;
>
> I've seen it done.

No, that is not what he means, that IS a main program.
In Ada 95 there is no requirement for a main program,
period!

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    




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

* Re: Can't export object of private type
  1999-03-10  0:00                         ` robert_dewar
@ 1999-03-10  0:00                           ` dennison
  1999-03-10  0:00                             ` robert_dewar
  1999-03-11  0:00                           ` Don Harrison
  1 sibling, 1 reply; 128+ messages in thread
From: dennison @ 1999-03-10  0:00 UTC (permalink / raw)


In article <7c68t9$vjk$1@nnrp1.dejanews.com>,
  robert_dewar@my-dejanews.com wrote:
> In article <7c6566$rps$1@nnrp1.dejanews.com>,
>   dennison@telepath.com wrote:
> > procedure Main is
> > begin
> >    null;  -- The with's do all the work
> > end;
>
> No, that is not what he means, that IS a main program.
> In Ada 95 there is no requirement for a main program,
> period!

Oh really?  How does that work? How does such a program get compiled or
invoked?

T.E.D.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    




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

* Re: Can't export object of private type
  1999-03-10  0:00                       ` dennison
@ 1999-03-10  0:00                         ` Robert A Duff
  1999-03-10  0:00                           ` dennison
  1999-03-10  0:00                           ` robert_dewar
  1999-03-10  0:00                         ` robert_dewar
  1 sibling, 2 replies; 128+ messages in thread
From: Robert A Duff @ 1999-03-10  0:00 UTC (permalink / raw)


dennison@telepath.com writes:

> procedure Main is
> begin
>    null;  -- The with's do all the work
> end;
> 
> I've seen it done. The problem is that any tasks that have terminate options
> will immediately complete. ...

No, that's not right.  Such tasks will not complete until all the other
tasks are done.

There's no harm in having a do-nothing main procedure, and in Ada 95 you
don't even have to have one at all.

- Bob
-- 
Change robert to bob to get my real email address.  Sorry.




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

* Re: Can't export object of private type
  1999-03-11  0:00                                 ` robert_dewar
@ 1999-03-11  0:00                                   ` Don Harrison
  1999-03-12  0:00                                     ` robert_dewar
  0 siblings, 1 reply; 128+ messages in thread
From: Don Harrison @ 1999-03-11  0:00 UTC (permalink / raw)


Robert Dewar wrote:

:In article <7c6thd$j94$1@nnrp1.dejanews.com>,
:  dennison@telepath.com wrote:
:> OK, how does this get implemented? I read the Aonix and
:> GreenHills manuals fairly thouroughly, and don't remember
:> comming across this. I don't remember seeing it in the
:> super-secret gnat documentation either, but I'll go look
:> now.
:
:well one obvious way for GNAT is to bind with the -n switch
:then use a driver that calls adainit and adafinal.

In other words, the main program is still required. It's just external to 
the Ada code being compiled.


-- 
Don (Harrison).   donh at syd.csa.com.au






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

* Re: Can't export object of private type
  1999-03-10  0:00                         ` robert_dewar
  1999-03-10  0:00                           ` dennison
@ 1999-03-11  0:00                           ` Don Harrison
  1 sibling, 0 replies; 128+ messages in thread
From: Don Harrison @ 1999-03-11  0:00 UTC (permalink / raw)


Robert Dewar wrote:

:In Ada 95 there is no requirement for a main program, period!

How do I get GNAT to bind this?..
 
package Not_a_Main_Program is
pragma Elaborate_Body;
end;

with Text_Io; use Text_IO;
package body Not_a_Main_Program is
begin
  Put_Line ("I am not a main program");
end;


Using GNAT 3.11b:

gcc -c not_a_main_program.adb
gnatbind not_a_main_program.ali
error: "not_a_main_program.ali" does not contain a unit that can be a main program


-- 
Don (Harrison).   donh at syd.csa.com.au






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

* Re: Can't export object of private type
  1999-03-10  0:00                               ` dennison
  1999-03-11  0:00                                 ` dennison
  1999-03-11  0:00                                 ` bill
@ 1999-03-11  0:00                                 ` robert_dewar
  1999-03-11  0:00                                   ` Don Harrison
  2 siblings, 1 reply; 128+ messages in thread
From: robert_dewar @ 1999-03-11  0:00 UTC (permalink / raw)


In article <7c6thd$j94$1@nnrp1.dejanews.com>,
  dennison@telepath.com wrote:
> OK, how does this get implemented? I read the Aonix and
> GreenHills manuals fairly thouroughly, and don't remember
> comming across this. I don't remember seeing it in the
> super-secret gnat documentation either, but I'll go look
> now.

well one obvious way for GNAT is to bind with the -n switch
then use a driver that calls adainit and adafinal.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    




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

* Re: Can't export object of private type
  1999-03-10  0:00                               ` dennison
  1999-03-11  0:00                                 ` dennison
@ 1999-03-11  0:00                                 ` bill
  1999-03-11  0:00                                   ` Scott Ingram
                                                     ` (2 more replies)
  1999-03-11  0:00                                 ` robert_dewar
  2 siblings, 3 replies; 128+ messages in thread
From: bill @ 1999-03-11  0:00 UTC (permalink / raw)


In article <7c6thd$j94$1@nnrp1.dejanews.com>, dennison@telepath.com says...
>
 
...
> I don't remember
>seeing it in the super-secret gnat documentation either, but I'll go look now.
>
 
Please telll us the name of this secret gnat document, I am interested in
getting it also as I also started using gnat, and how did you get it? is it 
on some private web site somewhere I can download or is this one 
that only private customers of ACT can obtain? could one buy a copy?

regards,
bill





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

* Re: Can't export object of private type
  1999-03-10  0:00                               ` dennison
@ 1999-03-11  0:00                                 ` dennison
  1999-03-11  0:00                                 ` bill
  1999-03-11  0:00                                 ` robert_dewar
  2 siblings, 0 replies; 128+ messages in thread
From: dennison @ 1999-03-11  0:00 UTC (permalink / raw)


In article <7c6thd$j94$1@nnrp1.dejanews.com>,
  dennison@telepath.com wrote:
> In article <7c6qek$gcm$1@nnrp1.dejanews.com>,
>   robert_dewar@my-dejanews.com wrote:
> > In article <7c6bqr$2jb$1@nnrp1.dejanews.com>,
> >   dennison@telepath.com wrote:
> > > Oh really?  How does that work? How does such a program
> > > get compiled or invoked?
> >
> > Ask your friendly implementor, these questions are
> > obviously not ones that get answered by the RM!
>
> OK, how does this get implemented? I read the Aonix and GreenHills manuals
> fairly thouroughly, and don't remember comming across this. I don't remember
> seeing it in the super-secret gnat documentation either, but I'll go look now.

Nope, didn't see it in there either. I'm guessing w/ gnat you would do a
gnatmake with the name of a package that transitively with's everything you
need, but I didn't see anything specificly about that in the Gnat RM or User's
Guide.

T.E.D.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    




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

* Re: Can't export object of private type
  1999-03-10  0:00                           ` dennison
@ 1999-03-11  0:00                             ` dennison
  0 siblings, 0 replies; 128+ messages in thread
From: dennison @ 1999-03-11  0:00 UTC (permalink / raw)


In article <7c6t83$isn$1@nnrp1.dejanews.com>,
  dennison@telepath.com wrote:
> In article <wccn21lyzsl.fsf@world.std.com>,
>   Robert A Duff <bobduff@world.std.com> wrote:
> > dennison@telepath.com writes:
> >
> > > procedure Main is
> > > begin
> > >    null;  -- The with's do all the work
> > > end;
> > >
> > > I've seen it done. The problem is that any tasks that have terminate
options
> > > will immediately complete. ...
> >
> > No, that's not right.  Such tasks will not complete until all the other
> > tasks are done.
>
> Its been a while, but in Ada83 the way I remember it I would see any task that
> was a child of the main unit go to a "completed" state when the main unit
> completed and the task hit a terminate option, if it had no subtasks still
> running. Of course the program itself won't complete until all other tasks
> complete, but that didn't stop any one task from quitting.

OK. I went back and dug out my old Ada83 LRM (I knew I kept that thing for
some reason). It looks like one of three possible things was happening.

 1) My memory is completely faulty. (Stranger things have happened)
 2) My Ada83 compiler was buggy. I think it was DECAda, so I doubt it.
 3) I had a situation where *every* task had a terminate option, and the main
unit completed.

I suspect it was #3.

T.E.D.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    




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

* Re: Can't export object of private type
  1999-03-11  0:00                                 ` bill
  1999-03-11  0:00                                   ` Scott Ingram
@ 1999-03-11  0:00                                   ` dennison
  1999-03-12  0:00                                   ` dewar
  2 siblings, 0 replies; 128+ messages in thread
From: dennison @ 1999-03-11  0:00 UTC (permalink / raw)


In article <7c8deo$2n9@drn.newsguy.com>,
  bill@ wrote:
> In article <7c6thd$j94$1@nnrp1.dejanews.com>, dennison@telepath.com says...
> >
>
> ...
> > I don't remember
> >seeing it in the super-secret gnat documentation either, but I'll go look
now.
> >
>
> Please telll us the name of this secret gnat document, I am interested in
> getting it also as I also started using gnat, and how did you get it? is it
> on some private web site somewhere I can download or is this one
> that only private customers of ACT can obtain? could one buy a copy?

:-)

The "super-secret" gnat documentation I'm referring to is the manuals that
come with Gnat when you download it. On my NT box, I can get them by bringing
up the Start menu, selecting "Programs", then "Gnat Ada95 Compiler". There I
get a menu with "Ada GUI IDE", "Gnat Debugger", and 7 different sources of
documentation.

But remember, its a big secret. Don't tell a soul. If you are captured, the
company will disavow all knowledge of your mission. This posting will
self-destruct in 7 seconds...

T.E.D.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    




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

* Re: Can't export object of private type
  1999-03-11  0:00                                   ` Scott Ingram
@ 1999-03-11  0:00                                     ` Larry Kilgallen
  0 siblings, 0 replies; 128+ messages in thread
From: Larry Kilgallen @ 1999-03-11  0:00 UTC (permalink / raw)


In article <36E7D7DF.7CDB369D@silver.jhuapl.edu>, Scott Ingram <scott@silver.jhuapl.edu> writes:
> bill@ wrote:
>> 
>> In article <7c6thd$j94$1@nnrp1.dejanews.com>, dennison@telepath.com says...
>> >
>> 
>> ...
>> > I don't remember
>> >seeing it in the super-secret gnat documentation either, but I'll go look now.
>> >
>> 
>> Please telll us the name of this secret gnat document, I am interested in
>> getting it also as I also started using gnat, and how did you get it? is it
>> on some private web site somewhere I can download or is this one
>> that only private customers of ACT can obtain? could one buy a copy?
>> 
>> regards,
>> bill
> 
> Bill, 
> 
> I would be delighted to sell you as many copies as
> you need...

I will sell you MORE copies than you need, at DOUBLE Scott's price :-)




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

* Re: Can't export object of private type
  1999-03-11  0:00                                 ` bill
@ 1999-03-11  0:00                                   ` Scott Ingram
  1999-03-11  0:00                                     ` Larry Kilgallen
  1999-03-11  0:00                                   ` dennison
  1999-03-12  0:00                                   ` dewar
  2 siblings, 1 reply; 128+ messages in thread
From: Scott Ingram @ 1999-03-11  0:00 UTC (permalink / raw)


bill@ wrote:
> 
> In article <7c6thd$j94$1@nnrp1.dejanews.com>, dennison@telepath.com says...
> >
> 
> ...
> > I don't remember
> >seeing it in the super-secret gnat documentation either, but I'll go look now.
> >
> 
> Please telll us the name of this secret gnat document, I am interested in
> getting it also as I also started using gnat, and how did you get it? is it
> on some private web site somewhere I can download or is this one
> that only private customers of ACT can obtain? could one buy a copy?
> 
> regards,
> bill

Bill, 

I would be delighted to sell you as many copies as
you need...but I am sure that someone here will foil
my profit plans by pointing out that the user's guide
and reference manual are available at the same place
you got GNAT.  As for them being "super-secret," this refers
to the fact many GNAT users seem to be puzzled by
documentation that tells everything you could ever want
to know about using and abusing the compiler.  Where is
the mystery, the challenge, the need to post to USENET
if the answer can be looked up in the manual?  :)
-- 
Scott Ingram
Sonar Processing and Analysis Laboratory
Johns Hopkins University Applied Physics Laboratory




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

* Re: Can't export object of private type
  1999-03-11  0:00                                 ` bill
  1999-03-11  0:00                                   ` Scott Ingram
  1999-03-11  0:00                                   ` dennison
@ 1999-03-12  0:00                                   ` dewar
  2 siblings, 0 replies; 128+ messages in thread
From: dewar @ 1999-03-12  0:00 UTC (permalink / raw)


In article <7c8deo$2n9@drn.newsguy.com>,
  bill@ wrote:
> Please telll us the name of this secret gnat document, I
> am interested in getting it also as I also started using
> gnat, and how did you get it? is it  on some private web
> site somewhere I can download or is this one that only
> private customers of ACT can obtain? could one buy a
> copy?

Well that's certainly good for a chuckle :-)

Bill, I often refer to the openly available documentation
of GNAT as a secret source. It's a joke, inspired by the
fact that given how few people seem to read it, it might
as well be a closely guarded secret.

The documentation for GNAT is included with every release,
be sure to read both the users guide and the reference
manual cover to cover, there is lots of useful stuff there.

Robert Dewar
Ada Core Technologies

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    




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

* Re: Can't export object of private type
  1999-03-11  0:00                                   ` Don Harrison
@ 1999-03-12  0:00                                     ` robert_dewar
  0 siblings, 0 replies; 128+ messages in thread
From: robert_dewar @ 1999-03-12  0:00 UTC (permalink / raw)


In article <F8GCpL.5Lz@syd.csa.com.au>,
  nospam@thanks.com.au wrote:
> In other words, the main program is still required. It's
> just external to the Ada code being compiled.


You are getting confused by the terminology. Main program
is an Ada technical term, don't get that confused with
the informal use of the term!

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    




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

end of thread, other threads:[~1999-03-12  0:00 UTC | newest]

Thread overview: 128+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <F7JoCB.JxB@syd.csa.com.au>
1999-02-24  0:00 ` Can't export object of private type Don Harrison
1999-02-24  0:00   ` Tom Moran
1999-02-24  0:00   ` Samuel Mize
1999-02-24  0:00     ` Tucker Taft
1999-02-25  0:00     ` Don Harrison
1999-02-25  0:00       ` Samuel Mize
1999-02-26  0:00         ` Don Harrison
1999-02-27  0:00           ` Nick Roberts
1999-03-01  0:00             ` Don Harrison
1999-03-02  0:00               ` Matthew Heaney
1999-03-01  0:00             ` Don Harrison
1999-03-01  0:00               ` Matthew Heaney
1999-03-01  0:00                 ` Nick Roberts
1999-03-01  0:00               ` Nick Roberts
1999-03-01  0:00                 ` Don Harrison
1999-03-02  0:00                   ` Matthew Heaney
1999-03-03  0:00                     ` Don Harrison
1999-03-03  0:00                       ` Samuel Mize
1999-03-04  0:00                         ` Don Harrison
1999-03-07  0:00                     ` Ehud Lamm
1999-03-03  0:00               ` Robert A Duff
1999-03-04  0:00                 ` Don Harrison
1999-03-04  0:00                   ` Robert A Duff
1999-02-28  0:00         ` Matthew Heaney
1999-03-01  0:00           ` Nick Roberts
1999-03-01  0:00             ` Matthew Heaney
1999-03-01  0:00             ` Matthew Heaney
1999-03-02  0:00               ` Nick Roberts
1999-03-01  0:00           ` Samuel Mize
1999-02-25  0:00       ` fraser
1999-02-26  0:00         ` Don Harrison
     [not found]           ` <7b6nqe$75m$1@remarq.com>
1999-02-26  0:00             ` fraser
1999-02-27  0:00               ` Nick Roberts
1999-02-26  0:00           ` fraser
1999-03-01  0:00             ` Don Harrison
1999-03-01  0:00               ` Matthew Heaney
1999-02-26  0:00           ` Samuel Mize
1999-03-01  0:00             ` Don Harrison
1999-03-01  0:00               ` Matthew Heaney
1999-03-02  0:00               ` fraser
1999-03-03  0:00                 ` Don Harrison
1999-02-28  0:00           ` Matthew Heaney
1999-02-28  0:00         ` Matthew Heaney
1999-02-25  0:00       ` robert_dewar
1999-02-26  0:00         ` Don Harrison
1999-02-26  0:00           ` robert_dewar
1999-02-26  0:00             ` bourguet
1999-02-26  0:00               ` Samuel T. Harris
1999-02-27  0:00                 ` Jean-Pierre Rosen
1999-02-27  0:00                 ` Simon Wright
1999-02-28  0:00               ` dewar
1999-03-01  0:00                 ` bourguet
1999-02-26  0:00             ` dennison
1999-03-01  0:00             ` Stephen Leake
1999-03-01  0:00             ` Don Harrison
1999-03-01  0:00               ` robert_dewar
1999-03-03  0:00                 ` Don Harrison
1999-03-03  0:00                   ` robert_dewar
1999-02-27  0:00         ` Brian Rogoff
1999-03-01  0:00           ` robert_dewar
1999-02-28  0:00       ` Matthew Heaney
1999-03-01  0:00       ` Tom Moran
1999-03-02  0:00         ` Matthew Heaney
1999-03-02  0:00           ` Tom Moran
1999-03-02  0:00             ` Matthew Heaney
1999-03-02  0:00               ` Tom Moran
1999-03-02  0:00                 ` Matthew Heaney
1999-03-02  0:00                   ` nabbasi
1999-03-02  0:00                     ` Matthew Heaney
1999-03-03  0:00                   ` Don Harrison
1999-03-03  0:00                     ` Single Extension; Polymorphic Arrays Nick Roberts
1999-03-03  0:00                       ` Nick Roberts
1999-03-08  0:00                         ` Matthew Heaney
1999-03-08  0:00                           ` Tucker Taft
     [not found]                             ` <m3ogm40wav.fsf@mheaney.ni.net>
1999-03-08  0:00                               ` Nick Roberts
1999-03-08  0:00                               ` Tucker Taft
1999-03-08  0:00                                 ` dennison
1999-03-09  0:00                                 ` Nick Roberts
1999-03-08  0:00                           ` Nick Roberts
1999-03-03  0:00               ` Can't export object of private type Don Harrison
1999-03-03  0:00                 ` Don Harrison
1999-03-03  0:00                   ` Nick Roberts
1999-03-04  0:00                     ` Don Harrison
1999-03-04  0:00                       ` fraser
1999-03-09  0:00                         ` Don Harrison
1999-03-04  0:00                       ` Nick Roberts
1999-03-08  0:00                         ` Matthew Heaney
1999-03-09  0:00                         ` Don Harrison
1999-03-09  0:00                           ` Matthew Heaney
1999-03-09  0:00                             ` Nick Roberts
1999-03-10  0:00                             ` Don Harrison
1999-03-10  0:00                               ` Matthew Heaney
1999-03-04  0:00                       ` Nick Roberts
1999-03-04  0:00                         ` robert_dewar
1999-03-05  0:00                           ` Nick Roberts
1999-03-05  0:00                         ` Robert A Duff
1999-03-05  0:00                           ` Abstract Subprograms of Untagged Types Nick Roberts
1999-03-05  0:00                             ` robert_dewar
1999-03-05  0:00                             ` Tucker Taft
1999-03-05  0:00                               ` Nick Roberts
1999-03-06  0:00                               ` robert_dewar
1999-03-08  0:00                     ` Can't export object of private type Matthew Heaney
1999-03-08  0:00                       ` Nick Roberts
1999-03-08  0:00                 ` Matthew Heaney
1999-03-10  0:00                   ` Don Harrison
1999-03-10  0:00                     ` Matthew Heaney
1999-03-10  0:00                       ` dennison
1999-03-10  0:00                         ` Robert A Duff
1999-03-10  0:00                           ` dennison
1999-03-11  0:00                             ` dennison
1999-03-10  0:00                           ` robert_dewar
1999-03-10  0:00                         ` robert_dewar
1999-03-10  0:00                           ` dennison
1999-03-10  0:00                             ` robert_dewar
1999-03-10  0:00                               ` dennison
1999-03-11  0:00                                 ` dennison
1999-03-11  0:00                                 ` bill
1999-03-11  0:00                                   ` Scott Ingram
1999-03-11  0:00                                     ` Larry Kilgallen
1999-03-11  0:00                                   ` dennison
1999-03-12  0:00                                   ` dewar
1999-03-11  0:00                                 ` robert_dewar
1999-03-11  0:00                                   ` Don Harrison
1999-03-12  0:00                                     ` robert_dewar
1999-03-11  0:00                           ` Don Harrison
1999-03-03  0:00           ` Don Harrison
1999-02-28  0:00     ` Matthew Heaney
1999-02-28  0:00   ` Matthew Heaney

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