* 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-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 ` 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 ` 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 ` robert_dewar ` (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 ` robert_dewar 1999-02-26 0:00 ` Don Harrison 1999-02-27 0:00 ` Brian Rogoff 1999-02-25 0:00 ` fraser ` (3 subsequent siblings) 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 ` 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-26 0:00 ` Don Harrison @ 1999-02-26 0:00 ` robert_dewar 1999-02-26 0:00 ` dennison ` (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 ` dennison 1999-02-26 0:00 ` bourguet ` (2 subsequent siblings) 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 ` dennison @ 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 ` Don Harrison 1999-03-01 0:00 ` Stephen Leake 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 ` 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 ` 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-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 ` 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 ` 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-26 0:00 ` robert_dewar 1999-02-26 0:00 ` dennison 1999-02-26 0:00 ` bourguet @ 1999-03-01 0:00 ` Don Harrison 1999-03-01 0:00 ` robert_dewar 1999-03-01 0:00 ` Stephen Leake 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-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-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 ` 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-02-26 0:00 ` robert_dewar ` (2 preceding siblings ...) 1999-03-01 0:00 ` Don Harrison @ 1999-03-01 0:00 ` Stephen Leake 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-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-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-02-25 0:00 ` Don Harrison 1999-02-25 0:00 ` robert_dewar @ 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 ` Samuel Mize ` (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 ` fraser @ 1999-02-26 0:00 ` Don Harrison 1999-02-26 0:00 ` Samuel Mize ` (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-26 0:00 ` Don Harrison @ 1999-02-26 0:00 ` Samuel Mize 1999-03-01 0:00 ` Don Harrison [not found] ` <7b6nqe$75m$1@remarq.com> ` (2 subsequent siblings) 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 ` 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 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-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 ` 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
[parent not found: <7b6nqe$75m$1@remarq.com>]
* 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 ` 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-26 0:00 ` Don Harrison 1999-02-26 0:00 ` Samuel Mize [not found] ` <7b6nqe$75m$1@remarq.com> @ 1999-02-26 0:00 ` fraser 1999-03-01 0:00 ` Don Harrison 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 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-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-02-26 0:00 ` Don Harrison ` (2 preceding siblings ...) 1999-02-26 0:00 ` fraser @ 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 ` 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-25 0:00 ` Don Harrison 1999-02-25 0:00 ` robert_dewar 1999-02-25 0:00 ` fraser @ 1999-02-25 0:00 ` Samuel Mize 1999-02-26 0:00 ` Don Harrison 1999-02-28 0:00 ` Matthew Heaney 1999-02-28 0:00 ` Matthew Heaney 1999-03-01 0:00 ` Tom Moran 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 ` 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-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-27 0:00 ` Nick Roberts @ 1999-03-01 0:00 ` Don Harrison 1999-03-01 0:00 ` Nick Roberts ` (2 more replies) 1999-03-01 0:00 ` Don Harrison 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 ` Nick Roberts 1999-03-01 0:00 ` Don Harrison 1999-03-01 0:00 ` Matthew Heaney 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 ` 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-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-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-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-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-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: Can't export object of private type 1999-03-01 0:00 ` Don Harrison 1999-03-01 0:00 ` Nick Roberts @ 1999-03-01 0:00 ` Matthew Heaney 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-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-03-01 0:00 ` Don Harrison 1999-03-01 0:00 ` Nick Roberts 1999-03-01 0:00 ` Matthew Heaney @ 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
* 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-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-02-27 0:00 ` Nick Roberts 1999-03-01 0:00 ` Don Harrison @ 1999-03-01 0:00 ` Don Harrison 1999-03-02 0:00 ` Matthew Heaney 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 ` 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-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-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 ` 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-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-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-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-02-25 0:00 ` Don Harrison ` (2 preceding siblings ...) 1999-02-25 0:00 ` Samuel Mize @ 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 ` 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-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-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-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-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-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
* 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: 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: 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
[parent not found: <m3ogm40wav.fsf@mheaney.ni.net>]
* 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: 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 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: 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-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-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-03 0:00 ` Don Harrison @ 1999-03-03 0:00 ` Nick Roberts 1999-03-04 0:00 ` Don Harrison 1999-03-08 0:00 ` 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 ` Nick Roberts @ 1999-03-04 0:00 ` Don Harrison 1999-03-04 0:00 ` Nick Roberts ` (2 more replies) 1999-03-08 0:00 ` 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 ` Nick Roberts 1999-03-04 0:00 ` robert_dewar 1999-03-05 0:00 ` Robert A Duff 1999-03-04 0:00 ` Can't export object of private type fraser 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) 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 ` 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-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
* 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
* 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 ` Tucker Taft 1999-03-05 0:00 ` robert_dewar 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 ` Tucker Taft 1999-03-05 0:00 ` Nick Roberts 1999-03-06 0:00 ` robert_dewar 1999-03-05 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: 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: Abstract Subprograms of Untagged Types 1999-03-05 0:00 ` Abstract Subprograms of Untagged Types Nick Roberts 1999-03-05 0:00 ` Tucker Taft @ 1999-03-05 0:00 ` robert_dewar 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: Can't export object of private type 1999-03-04 0:00 ` Don Harrison 1999-03-04 0:00 ` Nick Roberts @ 1999-03-04 0:00 ` fraser 1999-03-09 0:00 ` Don Harrison 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 ` Can't export object of private type 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-04 0:00 ` Don Harrison 1999-03-04 0:00 ` Nick Roberts 1999-03-04 0:00 ` Can't export object of private type fraser @ 1999-03-04 0:00 ` Nick Roberts 1999-03-08 0:00 ` Matthew Heaney 1999-03-09 0:00 ` Don Harrison 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 ` 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: 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-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: 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-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 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-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-08 0:00 ` 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: 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-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-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 ` Matthew Heaney @ 1999-03-10 0:00 ` dennison 1999-03-10 0:00 ` robert_dewar 1999-03-10 0:00 ` Robert A Duff 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_dewar 1999-03-10 0:00 ` dennison 1999-03-11 0:00 ` Don Harrison 1999-03-10 0:00 ` Robert A Duff 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_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 ` dennison @ 1999-03-11 0:00 ` dennison 1999-03-11 0:00 ` robert_dewar 1999-03-11 0:00 ` bill 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 @ 1999-03-11 0:00 ` robert_dewar 1999-03-11 0:00 ` Don Harrison 1999-03-11 0:00 ` bill 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-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-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
* 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 ` robert_dewar @ 1999-03-11 0:00 ` bill 1999-03-11 0:00 ` dennison ` (2 more replies) 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-11 0:00 ` bill @ 1999-03-11 0:00 ` dennison 1999-03-11 0:00 ` Scott Ingram 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 ` bill 1999-03-11 0:00 ` dennison @ 1999-03-11 0:00 ` Scott Ingram 1999-03-11 0:00 ` Larry Kilgallen 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 ` 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 ` dennison 1999-03-11 0:00 ` Scott Ingram @ 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-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-10 0:00 ` robert_dewar @ 1999-03-10 0:00 ` Robert A Duff 1999-03-10 0:00 ` dennison 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-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-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-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-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-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-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
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 ` robert_dewar 1999-02-26 0:00 ` Don Harrison 1999-02-26 0:00 ` robert_dewar 1999-02-26 0:00 ` dennison 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-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-03-01 0:00 ` Stephen Leake 1999-02-27 0:00 ` Brian Rogoff 1999-03-01 0:00 ` robert_dewar 1999-02-25 0:00 ` fraser 1999-02-26 0:00 ` Don Harrison 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 [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-28 0:00 ` Matthew Heaney 1999-02-28 0:00 ` Matthew Heaney 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-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-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 1999-03-04 0:00 ` Robert A Duff 1999-03-01 0:00 ` Don Harrison 1999-03-02 0:00 ` Matthew Heaney 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-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 ` 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 ` Tucker Taft 1999-03-05 0:00 ` Nick Roberts 1999-03-06 0:00 ` robert_dewar 1999-03-05 0:00 ` robert_dewar 1999-03-04 0:00 ` Can't export object of private type 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-08 0:00 ` 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_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 ` robert_dewar 1999-03-11 0:00 ` Don Harrison 1999-03-12 0:00 ` robert_dewar 1999-03-11 0:00 ` bill 1999-03-11 0:00 ` dennison 1999-03-11 0:00 ` Scott Ingram 1999-03-11 0:00 ` Larry Kilgallen 1999-03-12 0:00 ` dewar 1999-03-11 0:00 ` Don Harrison 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-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