LSN019.GenlDisc ------------------------ !topic LSN on Generalized Discriminants $Revision: 1.1 $ !reference MS-3.6.1 !from Tucker Taft 91-10-30 $Date: 91/10/30 18:59:23 $ !discussion We have proposed that Tasks and Protected Records may have discriminants, and that discriminants in general may be of any elementary type. There seem to have been two concerns with this proposal: 1) Discriminants checks for non-discrete discriminants seem unlikely to be very useful. 2) At least for tasks, why limit the discriminants to being elementary types? First we will explain our original rationale, and then suggest some alternatives, and finally make some new proposals. With regard to (1), we have not worried very much about discriminant checks, because we believe it will be relatively unusual to use discriminants for both generally parameterizing a type, while at the same time using them to determine the "shape" of the type. With regard to (2), we felt that elementary types were sufficient because of the availability of access types, and were easy to handle because they had the nice property of being small, of statically-known size, and always having a well-defined copy operation. However, both of the above arguments are a bit weak, so we have been prompted by DR comments to consider other alternatives. For handling (1), one obvious alternative is: 1a) A discriminant check only checks the discrete discriminants for equality. The others are treated as though they are "unconstrained" and therefore can be changed by whole object assignment. Another alternative is: 1b) Allow the use of an explicit parameter mode "in" (and perhaps "access") for "type parameters." Type parameters without an explicit parameter mode must be discrete, and are called "discriminants." Only the discriminants may be used to specify bounds for nested arrays, specify discriminants for nested parameterized types, or control a variant part. Only discriminants are checked by a discriminant check. Yet another alternative: 1c) Only limited types may have non-discrete type parameters. This minimizes the problem because constraint checks rarely occur for limited types (since they don't allow initialization or assignment). We could disallow the use of a constrained subtype for a formal parameter of a limited type with non-discrete type parameters, or only check the discrete type parameters. Still one more: 1d) Only type parameters which are used to specify a bound for an array subcomponent or to control a variant are checked by a discriminant check. This last one is actually my favorite, since it directly addresses the question of discriminants which control the "shape." Such discriminants are already given special treatment in record aggregates, because they must be evaluated first if determining the bounds of an array subaggregate with an others choice, and must be static when controlling a variant. For answering (2), an alternative is the following: 2a) Limited types may have elementary or composite discriminants/type-parameters. Combining 1d) and 2a) might lead to the following proposal: A) Non-limited composite types may have discrete discriminants. B) Limited composite types may have type parameters of any type, of mode "in" or mode "access." C) Only "in" mode discrete discriminants/type-parameters may be used to specify an array bound, or control a variant. D) Only those discriminants which specify an array bound, or control a variant, are checked on a discriminant check. Part (B) of the above mentions mode "access." This has two uses: 1) To parameterize a task with an access to an aliased variable, to be updated, etc. as part of the job of the task. (See the recent LSN on mode "access".) 2) To provide a building block for multiple inheritance. ASIDE ON MULTIPLE INHERITANCE The multiple inheritance point needs a further example: One critical aspect of multiple inheritance is to allow a single object to masquerade as a member of more than one class. Generic "mixins" can be used to some effect, but not to the point of allowing the object to be on heterogenous lists for multiple classes. Imagine the following example: There is a class "window" which represents a window to appear on a screen. There is a class "view-of-spreadsheet" which represents some object which has a "hot link" to a spreadsheet, i.e., will be informed anytime the "viewed" spreadsheet is updated. Now we want to construct a window which has a hot-link to some spreadsheet. The window needs to be linked into the window tree managed by the window manager. Because it is hot-linked to a spreadsheet, it wants to be on the list of objects to be notified when the spreadsheet is updated. -- Here are the two class roots: type Window is tagged limited private; procedure Display(W : access Window) is <>; type View_Of_Spreadsheet is tagged limited private; procedure Notify(VOS : access View_Of_Spreadsheet) is <>; -- Here is the spreadsheet operation for creating a hot link -- between the View and the Spreadsheet: type View_Handle is access View_Of_Spreadsheet'CLASS; type Spreadsheet is tagged limited private; procedure Create_Hot_Link (SS : access Spreadsheet; VOS : View_Handle) is <>; -- After creating the hot link, Notify(VOS) will be called -- any time the spreadsheet is updated. -- NOW... Presume we want to create a window which has a hot-link -- to some spreadsheet. type View_From_A_Window(Enclosing_Window : access Window'CLASS) is new View_Of_Spreadsheet with record . . . end record; procedure Notify(VFAW : access View_From_A_Window) is begin Display(VFAW.Endlosing_Window); -- Update window display end Notify; type Window_With_A_View is new Window with record View : View_From_A_Window(Window_With_A_View'ACCESS); . . . end record; procedure Display(WVAV : access Window_With_A_View) is ... We now have two types which can reference each other, one as a component, the other as a by-access discriminant. The 'ACCESS attribute is being generalized to be usable within a record definition to produce a reference to the enclosing object. Given two such types, we can provide the functionality of multiple inheritance, without having to worry about the issues of colliding name spaces, etc., because we have kept the two interrelated types separate, while allowing them to reference each other. The mode "access" for discriminants/type-parameters makes this possible in a relatively manageable way. END OF ASIDE ON MULTIPLE INHERITANCE Comments on the proposals (A)-(D), on the other alternatives, or on the multiple inheritance "building block" are welcome. The sooner the better... -Tuck ========================