* premature use of private @ 1999-08-17 0:00 tmoran 1999-08-17 0:00 ` David C. Hoos, Sr. 1999-08-17 0:00 ` Matthew Heaney 0 siblings, 2 replies; 8+ messages in thread From: tmoran @ 1999-08-17 0:00 UTC (permalink / raw) I'm given an existing program that processes Apples with routines like function Is_Ripe(X : Apple) return Boolean; function Is_Red(X : Apple) return Boolean; function Size(X : Apple) return Integer; and type Pile is array(integer range <>) of Apple; procedure Sort_By_Size(X : in out Pile); I now need to add Oranges and Grapefruit and ... So I tried type Fruit is abstract tagged private; function Is_Ripe(X : Fruit) return Boolean; function Size(X : Fruit) return Integer; type Apple is new Fruit with private; function Is_Red(X : Apple) return Boolean; type Orange is new Fruit with private; function Florida(X : Orange) return Boolean; So far so good. But I don't want a Pile of mixed Fruit, so, borrowing from Barnes' on Containers, I tried: generic type This_Fruit is abstract tagged private; type Fruit_Ptr is access all This_Fruit; package Sets is type Pile is array(integer range <>) of Fruit_Ptr; procedure Sort_By_Size(X : in out Pile); end Sets; type Apple_Ptr is access all Apple; package Apples is new Sets(Apple, Apple_Ptr); But that won't work because Apple is private at this point. How should this be done? ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: premature use of private 1999-08-17 0:00 premature use of private tmoran @ 1999-08-17 0:00 ` David C. Hoos, Sr. 1999-08-17 0:00 ` Matthew Heaney 1 sibling, 0 replies; 8+ messages in thread From: David C. Hoos, Sr. @ 1999-08-17 0:00 UTC (permalink / raw) <tmoran@bix.com> wrote in message news:In2u3.3680$z6.293053@typhoon-sf.snfc21.pbi.net... > I'm given an existing program that processes Apples with routines like > function Is_Ripe(X : Apple) return Boolean; > function Is_Red(X : Apple) return Boolean; > function Size(X : Apple) return Integer; > and > type Pile is array(integer range <>) of Apple; > procedure Sort_By_Size(X : in out Pile); > > I now need to add Oranges and Grapefruit and ... > So I tried > > type Fruit is abstract tagged private; > function Is_Ripe(X : Fruit) return Boolean; > function Size(X : Fruit) return Integer; > > type Apple is new Fruit with private; > function Is_Red(X : Apple) return Boolean; > > type Orange is new Fruit with private; > function Florida(X : Orange) return Boolean; > > So far so good. But I don't want a Pile of mixed Fruit, so, > borrowing from Barnes' on Containers, I tried: > > generic > type This_Fruit is abstract tagged private; > type Fruit_Ptr is access all This_Fruit; > package Sets is > type Pile is array(integer range <>) of Fruit_Ptr; > procedure Sort_By_Size(X : in out Pile); > end Sets; > > type Apple_Ptr is access all Apple; > package Apples is new Sets(Apple, Apple_Ptr); > > But that won't work because Apple is private at this point. > > How should this be done? A generic instantiation can be declared (at least with GNAT) only at a point where the body(ies) of the actual type(s) with which it is instantiated are available; Further, it seems to me that to provide for new extensions without alteration of existing source files, the derived types should be in their own packages. Third, it seems that Size and Is_Ripe are intended to be class-wide functions, and should therefore have formal parameters of Fruit'Class; Alternatively, if they are not class-wide, they should be declared abstract so as to require overriding in any type derived from Fruit. Fourth, based on the English meaning of the identifiers, it doesn't seem that Sort_By_Size would need to be generic, nor that other operations on sets of fruit would need (nor could be) specialized for (as yet) undefined derived types, but perhaps the real abstraction is different. Having said all that, here's a skeleton of how I would approach it, not knowing any more about the abstraction. package Fruit is type Fruit is abstract tagged private; function Is_Ripe (X : Fruit'Class) return Boolean; function Size (X : Fruit'Class) return Positive; generic type This_Fruit is new Fruit with private; type Fruit_Ptr is access all This_Fruit; package Sets is type Pile is array (Positive range <>) of Fruit_Ptr; procedure Sort_By_Size (X : in out Pile); end Sets; private type Fruit is tagged record Ripe : Boolean; Size : Positive; end record; end Fruit; package Fruit.Apples is type Apple is new Fruit with private; function Is_Red (X : Apple) return Boolean; type Color is (Green, Red, Yellow); private type Apple is new Fruit with record Col : Color; end record; end Fruit.Apples; package Fruit.Oranges is type Orange is new Fruit with private; function Florida (X : Orange) return Boolean; type Origin is (California, Florida); private type Orange is new Fruit with record Orig : Origin; end record; end Fruit.Oranges; with Fruit.Apples; with Fruit.Oranges; procedure Do_Things_With_Fruit is type Apple_Ptr is access all Fruit.Apples.Apple; package Apples is new Fruit.Sets (Fruit.Apples.Apple, Apple_Ptr); begin null; end Do_Things_With_Fruit; ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: premature use of private 1999-08-17 0:00 premature use of private tmoran 1999-08-17 0:00 ` David C. Hoos, Sr. @ 1999-08-17 0:00 ` Matthew Heaney 1999-08-17 0:00 ` tmoran 1 sibling, 1 reply; 8+ messages in thread From: Matthew Heaney @ 1999-08-17 0:00 UTC (permalink / raw) In article <In2u3.3680$z6.293053@typhoon-sf.snfc21.pbi.net> , tmoran@bix.com wrote: > So far so good. But I don't want a Pile of mixed Fruit, so, > borrowing from Barnes' on Containers, I tried: > > generic > type This_Fruit is abstract tagged private; > type Fruit_Ptr is access all This_Fruit; > package Sets is > type Pile is array(integer range <>) of Fruit_Ptr; > procedure Sort_By_Size(X : in out Pile); > end Sets; > > type Apple_Ptr is access all Apple; > package Apples is new Sets(Apple, Apple_Ptr); > > But that won't work because Apple is private at this point. > > How should this be done? In order to instantiate the package, you need the full view of the type. I would declare the instantiations as children of the package in which the type is declared, e.g.: package Fruit is type Fruit_Type is ...; type Apple_Type is new Fruit_Type with private; type Apple_Ptr is access all Apple_Type; ... end Fruit; generic type This_Fruit is abstract tagged private; --or type This_Fruit is new Fruit_Type with private; type Fruit_Ptr is access all This_Fruit; --or, rather than importing the access type as a generic formal type, --just declare it locally, in the spec of Sets. package Fruit.Sets is type Pile is array(integer range <>) of Fruit_Ptr; procedure Sort_By_Size(X : in out Pile); end Fruit.Sets; Now, for the instantiation: with Fruit.Sets; package Fruit.Apple_Sets is new Fruit_Sets (Apple_Type, Apple_Ptr); If you go with the child package idea (suggested by David Hoos), then you structure the hierarchy as: package Fruit is type Fruit_Type is abstract tagged private; ... end Fruit; package Fruit.Apples is type Apple_Type is new Fruit_Type with private; type Apple_Ptr is access all Apple_Type; -- or Apple_Type'Class ... end Fruit.Apples; with Fruit.Sets; package Fruit.Apples.Sets is new Fruit.Sets (Apple_Type, Apple_Ptr); You don't have to cram the entire world in one package -- break it up into a package hierarchy. The idea is to always submit as little program text to the compiler as possible. -- Matt It is impossible to feel great confidence in a negative theory which has always rested its main support on the weak points of its opponent. Joseph Needham, "A Mechanistic Criticism of Vitalism" ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: premature use of private 1999-08-17 0:00 ` Matthew Heaney @ 1999-08-17 0:00 ` tmoran 1999-08-17 0:00 ` David C. Hoos, Sr. 1999-08-18 0:00 ` Matthew Heaney 0 siblings, 2 replies; 8+ messages in thread From: tmoran @ 1999-08-17 0:00 UTC (permalink / raw) > package Fruit.Apple_Sets is > new Fruit_Sets (Apple_Type, Apple_Ptr); The fruit stand operator wants a pretty display, so he needs function Prettier_Than(X : Fruit_Type) return Fruit.Apple_Sets.Pile; function Prettier_Than(X : Fruit_Type) return Fruit.Orange_Sets.Pile; etc. for those occasions when he wants to display a nice apple surrounded by even prettier oranges from his stock, or whatever. Does he need with Fruit, Fruit.Apple_Sets, Fruit.Orange_Sets; package Getting_Complicated is function Prettier_Than(X : Fruit_Type) return Fruit.Apple_Sets.Pile; function Prettier_Than(X : Fruit_Type) return Fruit.Orange_Sets.Pile; ... It seems unreasonable that it should be so much trouble just to declare a simple *homogenous* array. I understand that the compiler has a probem with an array when it doesn't yet know the size of its elements, but here the elements are all pointers, so that isn't a problem. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: premature use of private 1999-08-17 0:00 ` tmoran @ 1999-08-17 0:00 ` David C. Hoos, Sr. 1999-08-18 0:00 ` Matthew Heaney 1 sibling, 0 replies; 8+ messages in thread From: David C. Hoos, Sr. @ 1999-08-17 0:00 UTC (permalink / raw) <tmoran@bix.com> wrote in message news:Lgju3.398$06.54131@typhoon-sf.snfc21.pbi.net... > > package Fruit.Apple_Sets is > > new Fruit_Sets (Apple_Type, Apple_Ptr); > The fruit stand operator wants a pretty display, so he needs > function Prettier_Than(X : Fruit_Type) return Fruit.Apple_Sets.Pile; > function Prettier_Than(X : Fruit_Type) return Fruit.Orange_Sets.Pile; > etc. > for those occasions when he wants to display a nice apple surrounded > by even prettier oranges from his stock, or whatever. Does he need > with Fruit, Fruit.Apple_Sets, Fruit.Orange_Sets; No. mentioning a child pacage in a context clause gives visibility to the child and all of its ancestors. > package Getting_Complicated is > function Prettier_Than(X : Fruit_Type) return Fruit.Apple_Sets.Pile; > function Prettier_Than(X : Fruit_Type) return Fruit.Orange_Sets.Pile; > ... > It seems unreasonable that it should be so much trouble just to > declare a simple *homogenous* array. I understand that the compiler > has a probem with an array when it doesn't yet know the size of its > elements, but here the elements are all pointers, so that isn't > a problem. Have you forgotten that your Set package is more than just a "homogeneous" array of pointers? You've declared an operation Sort_By_Size which implies dereferencing those pointers and performing operations on the object itself. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: premature use of private 1999-08-17 0:00 ` tmoran 1999-08-17 0:00 ` David C. Hoos, Sr. @ 1999-08-18 0:00 ` Matthew Heaney 1999-08-18 0:00 ` tmoran 1 sibling, 1 reply; 8+ messages in thread From: Matthew Heaney @ 1999-08-18 0:00 UTC (permalink / raw) In article <Lgju3.398$06.54131@typhoon-sf.snfc21.pbi.net> , tmoran@bix.com wrote: > with Fruit, Fruit.Apple_Sets, Fruit.Orange_Sets; The statement with Fruit.Apple_Sets, Fruit.Orange_Sets; will do. > package Getting_Complicated is > function Prettier_Than(X : Fruit_Type) return Fruit.Apple_Sets.Pile; > function Prettier_Than(X : Fruit_Type) return Fruit.Orange_Sets.Pile; > ... > It seems unreasonable that it should be so much trouble just to > declare a simple *homogenous* array. Then perhaps you overcommitted. Your access type is a pointer to a specific kind of fruit (Apple_Ptr, Orange_Ptr, etc). This gives you a static guarantee about the specific type designated by the access object. If you don't need that much to be known statically, then you can loosen up the types by simply using an access type that designates Fruit_Type'Class. You wouldn't even need the generic anymore. You make the rule ("precondition") that it's up to the client to make sure that the array is populated by only one type. > I understand that the compiler has a probem with an array when it doesn't yet > know the size of its elements, but here the elements are all pointers, so that > isn't a problem. Then just make an array of type Fruit_Access is access all Fruit_Type'Class; type Fruit_Array is array (Positive range <>) of Fruit_Access; You can then write functions like: function Apples_Prettier_Than (X : Fruit_Type) return Fruit_Array; with a postcondition that all components of the return value are of specific type Apple_Type; and function Oranges_Prettier_Than (X : Fruit_Type) return Fruit_Array; with a postcondition that all components of the return value are of specific type Orange_Type. Remember that not all constraints have to be satisfied statically by the compiler (by using pointers to specific types). Use pointers to the class-wide root, and specify pre- and post- conditions about the nature of the actual specific type designated. -- Matt It is impossible to feel great confidence in a negative theory which has always rested its main support on the weak points of its opponent. Joseph Needham, "A Mechanistic Criticism of Vitalism" ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: premature use of private 1999-08-18 0:00 ` Matthew Heaney @ 1999-08-18 0:00 ` tmoran 1999-08-18 0:00 ` Matthew Heaney 0 siblings, 1 reply; 8+ messages in thread From: tmoran @ 1999-08-18 0:00 UTC (permalink / raw) >If you don't need that much to be known statically, then you can loosen up >the types by simply using an access type that designates Fruit_Type'Class. >You wouldn't even need the generic anymore. You make the rule >("precondition") that it's up to the client to make sure that the array is >populated by only one type. Exactly what I want to avoid. The whole intent was to get the compiler to statically check that the array is homogenous. It is, I gather, not possible to do this and to make generic subprograms that operate on such a homogenous array - but homogeneous on different types. So either I can use the generic, but it will need to dynamically check homogeneity, or I can not use a generic, but instead re-copy the relevant code, once for Apple_Set, once for Orange_Set, etc. One is ugly and wasteful at run time, the other is ugly and wasteful at compile time. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: premature use of private 1999-08-18 0:00 ` tmoran @ 1999-08-18 0:00 ` Matthew Heaney 0 siblings, 0 replies; 8+ messages in thread From: Matthew Heaney @ 1999-08-18 0:00 UTC (permalink / raw) In article <0ZCu3.300$26.56649@typhoon-sf.snfc21.pbi.net> , tmoran@bix.com wrote: > The whole intent was to get the compiler to statically check that the array is > homogenous. It is, I gather, not possible to do this and to make generic > subprograms that operate on such a homogenous array - but homogeneous on > different types. I woudn't say that. How about if we keep your generic set package, but make Better_Than a generic too: generic procedure Fruit.Sets.Better_Than_G (This_Fruit : Fruit_Type) return Pile; -- (Not sure if Pile needs expanded name) Now you can just create another child of your set instantiations: with Fruit.Sets.Better_Than_G; procedure Fruit.Apple_Sets.Better_Than is new Fruit.Apple_Sets.Better_Than_G; with Fruit.Sets.Better_Than_G; procedure Fruit.Orange_Sets.Better_Than is new Fruit.Orange_Sets.Better_Than_G; > So either I can use the generic, but it will need to dynamically check > homogeneity, No -- you're missing the point of a "precondition." It is NOT up to you the supplier to make sure that an array is really homogeneneous; that is the client's responsibility. If the client fails to satisfy the precondition, then it's his problem. > or I can not use a generic, but instead re-copy the relevant > code, once for Apple_Set, once for Orange_Set, etc. No -- you can use a generic. The generic function can be a child of the generic set package (as illustrated above), or, you can make it a sibling that imports the instantiation as a generic formal package: with Fruit.Sets; -- a better name would be "Fruit.Sets_G" generic with package Fruit_Sets is new Fruit.Sets (<>); -- need actual params? function Fruit.Better_Than_G (This_Fruit : Fruit_Type) return Fruit_Sets.Pile; > One is ugly and wasteful at run time, the other is ugly and wasteful at > compile time. It is only wasteful at run-time if you explicitly check the precondition. If you want to do so during development, I won't argue too much. But I don't agree that a supplier should always check -- especially in a delivered system -- the preconditions that are up to the client to satisfy. Stop mistrusting the client. Read Meyer's OOSC (either ed.) for the best explication of this topic. And yes, a generic Better_Than is possible, so there's no ugliness at compile-time either. -- Matt It is impossible to feel great confidence in a negative theory which has always rested its main support on the weak points of its opponent. Joseph Needham, "A Mechanistic Criticism of Vitalism" ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~1999-08-18 0:00 UTC | newest] Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 1999-08-17 0:00 premature use of private tmoran 1999-08-17 0:00 ` David C. Hoos, Sr. 1999-08-17 0:00 ` Matthew Heaney 1999-08-17 0:00 ` tmoran 1999-08-17 0:00 ` David C. Hoos, Sr. 1999-08-18 0:00 ` Matthew Heaney 1999-08-18 0:00 ` tmoran 1999-08-18 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