The mechanism for producing generic modules that is shown here is of less complexity than similar mechanisms used in Ada C++; it is of similar complexity to the mechanism used in Modula-3. In Ada, Modula-3 and Modula-2 the generic entities coincide with the separate compilation entities. In C++ the generic entities are 'template classes' and 'template functions'. The allowed kinds of generic parameters are more diverse: Ada allows types, constants, subprograms and variables, whereas Modula-2 and C++ only allow types and constants (which includes procedure constants in Modula-2). Modula-3 allows only the names of interfaces to be parameters to generic modules.
Standard Generic Modula-2 is a novel but very slight extension (by a single keyword and some syntax) of ISO Standard Modula-2. For this modest investment one obtains all the functionality of the static generic facilities already present in such languages as Modula-3 and C++. In addition, refinement of generic separate modules as local modules allows the module container to be a mechanism for the composition of one or more existing generic modules into a new module with more or less functionality than the original modules‹something not possible, for instance, in Modula-3.
Much of this functionality (and some other things) can also be obtained with object oriented mechanisms in various languages, but static generic modules are simpler, easier to use, and easier to debug than complex object oriented programs. In many cases (indeed in most) such modules are all that are needed to implement abstract data types even for large scale applications. The programmer who also has object oriented facilities available is engouraged to use both facilities, either separately, or in combination. Object oriented Moduila-2 extensions are the subject of a separate international standard, and will be discussed in detail in a later chapter of this book.
One should also note that with the mechanisms introduced in Generic Modula-2 for partial, composed, or extended refinement of generic separate modules as local modules, scalability is no longer confined to procedures and objects, for modules become scalable as well. That is, modules can also be easily composed into new modules with different functionality than the ones going into the mix.
This additional functionality does come with a cautionary note, however. It is not a good idea to build complex composed hierarchies, whether of procedures, modules, or objects. When such things are done, greater abstraction may be achieved, but it is too easy to lose track altogether of the details of implementation and thus to make it almost impossible to fix bugs. Moreover, excessive composition can lead to the production of very slow code. Composed hierarchies should therefore be no more than a few levels deep so as to promote code maintainability.