jwg1@bunny.gte.com (James W. Gish) (04/27/89)
I have come across the following problem with parameterized classes. I would appreciate any comments you might have on the problem or its resolution. Suppose I have three tables declared in my root class: term_table: H_TABLE[ TERM ]; attribute_table: H_TABLE[ ATTRIBUTE ]; cluster_table: H_TABLE[ CLUSTER ]; I want to have a routine that prompts the user for a unique name: get_unique_name( table: H_TABLE ): STRING is local is_unique : BOOLEAN do from is_unique := FALSE until is_unique do -- prompt for the name Result := prompt_for_name(...); -- check for uniqueness in the specified table is_unique := not table.present( Result ); end; end; And I want to be able to get names for TERMs, ATTRIBUTEs, and CLUSTERs that are unique w.r.t. the corresponding tables: unique_term_name, unique_cluster_name, unique_attr_name: STRING; unique_term_name := get_unique_name( term_table ); unique_attribute_name := get_unique_name( attribute_table ); unique_cluster_name := get_unique_name( cluster_table ); The compiler does not complain about the formal argument from the routine declaration: get_unique_name( table: H_TABLE ) ... However, it does complain about the following: is_unique := not table.present( Result ); with the error message: "Incorrect number of actual generic parameters for class h_table" In general, I see the problem here. You need to fix the actual parameter of H_TABLE so that you don't attempt to invoke features of table entries that don't exist. For example, if TERM had a feature foo and ATTRIBUTE did not, you want to avoid calling table.element( "KEY").foo However, in the cases where the compiler can figure out that reference to the elements of H_TABLE are not being made, this is overly restrictive. The solution I came up with is ugly, but the only one I could figure out given the current language definition: Define class TABLE end; -- TABLE and inherit TABLE in TERM, ATTRIBUTE and CLUSTER. Then the declaration of get_unique_name becomes: get_unique_name( table: H_TABLE[ TABLE ] ): STRING is ... This works fine but I shouldn't have to muck with TERM, ATTRIBUTE, and CLUSTER to accomplish this. It really violates information hiding principles and inhibits reusability. What I would like, is for the compiler to figure out which cases are legal. In the absence of that, I propose a form of constrained parameterization. For example, get_unique_name( table: H_TABLE[->TERM;CLUSTER;ATTRIBUTE] ): STRING ... This says that the actual parameter corresponding to table must be one of H_TABLE[TERM], H_TABLE[CLUSTER] or H_TABLE[ATTRIBUTE]. This would free me from TERM, CLUSTER, and ATTRIBUTE having to know about TABLE, which they SHOULDN'T know about. It would also allow the compiler to check for existence of features like foo in the above example. Any comments? -- Jim Gish GTE Laboratories, Inc., Waltham, MA CSNET: jgish@gte.com UUCP: ..!harvard!bunny!jwg1