======= LSN008.FormlPkg ======= !topic LSN on Generic Formal Packages !reference MD-12.1.4;2.0 !from Tucker Taft 91-06-04 !discussion > Could someone please provide a reasonable example or reason why one > would want Packages as formal generic parameters? To date I have not > come up with anything useful. > ...stephen That sounds like an excuse for an LSN... Here is the "canonical" example of layered generics: generic type Float_Type is digits <>; package Generic_Complex_Functions is type Complex is record Real, Imag : Float_Type; end record; function "+"(Left, Right : Complex) return Complex; function "-"(Left, Right : Complex) return Complex; function "*"(Left, Right : Complex) return Complex; function "abs"(Right : Complex) return Float_Type; . . . end Generic_Complex_Functions; . . . package Long_Complex is new Generic_Complex_Functions(Long_Float); Having already defined a generic package which implements complex numbers, we now want to define a generic package which implements complex matrices. Presume there is an existing instantiation of the Generic_Complex_Functions package (e.g. Long_Complex), and one wants to create an instantiation of the generic-complex-matrix package which can interoperate with that preexisting instantiation. Passing in the instantiation is the natural way to do this. Hence: generic with package Complex_Pkg is new Generic_Complex_Functions(<>); package Generic_Complex_Matrix_Operations is type Complex_Matrix is array(Positive range <>, Positive range <>) of Complex_Pkg.Complex; function "*"(Left, Right : Complex_Matrix) return Complex_Matrix; function "*"(Left : Complex_Pkg.Complex; Right : Complex_Matrix) return Complex_Matrix; . . . end Generic_Complex_Matrix_Operations; . . . package My_Cmplx_Mtrx is new Generic_Complex_Matrix_Operations(Long_Complex); An alternative mechanism would have a generic formal private type with each of the operations as additional formal parameters. Anyone who has used Ada-83 generics heavily has seen that this rapidly gets out of hand, with larger and larger generic formal parts as the depth of the layering increases. Passing in the instantiation captures the type and the operations all in a single generic parameter. In this case, it is intentional that the type be a visible record type, and there is *no* way to pass in a visible record type currently to a generic. The Numerics Working Group has singled out the generic formal package as particularly important to their work, because much of what they write is formulated as generics. ---------------- Another application of the ability to pass in an instantiation is when there are a group of types and/or operations which together represent some useful abstraction like a (mathematical) "group" or "ring" or "ideal" or ... One could define this abstraction via a generic formal part on an empty package spec. E.g: generic type Group_Element is private; Identity : constant Group_Element; function Op(Left, Right: Group_Element) return Group_Element; function Inverse(Right : Group_Element) return Group_Element; package Group_Signature is end; To proclaim that a type is a group over some operation one "instantiates" this signature. E.g.: package Integer_Addition_Group is new Group_Signature(Integer, Identity => 0, Op => "+", Inverse => "-" ); Later, if one has another generic which is meaningful for any "group" one can accept any instantiation of the Group_Signature generic. E.g.: generic with package Some_Group is new Group_Signature(<>); package Derived_Group_Operations is function Power(Left : Some_Group.Group_Element; Right : Integer) return Some_Group.Group_Element; -- Applies Op of group to left operand the number of times -- specified by absolute value of right operand. -- Returns Identity if Right is zero. -- Returns Inverse of result if right operand is negative. . . . end Derived_Group_Operations; ================= Note that the proposed "generic formal derived type" is an analogous capability. The generic formal package allows one to define additional operations and composite types (e.g. a matrix type) for the class of types corresponding to the types produced by the various instantiations of a generic package. The generic formal derived type allows one to define additional operations and composite types for the class of types rooted at a given type. My LSN on class-wide operations hopefully provides further insight to this analogy. -Tuck