!topic LSN on Deferred Constants of Any Type !key LSN-1038 on Deferred Constants of Any Type !reference MS-7.4.4;4.6 !from Bob Duff $Date: 92/10/08 18:37:20 $ $Revision: 1.1 $ !discussion This Language Study Note discusses the Ada 9X ability to declare deferred constants of any type. In Ada 83, the type of a deferred constant must be a private type, and that private type must be declared in the same package. Ada 9X removes this restriction -- a deferred constant can be of any type. The following discussion lists several reasons for removing the restriction. Although MS;4.6 does not say so, we also intend to remove the requirement to place a deferred constant in a package, in support of pragma Import (see below) -- the ILS will make this clear. The most obvious reason for removing the restriction is that Ada programmers view it as an "arbitrary restriction", and, indeed, there is no semantic need for the restriction. Arbitrary restrictions frustrate programmers, and give Ada a bad name. The most important reason for removing the restriction is for full support of pragma Import. One major reason for projects to choose C or C++ over Ada is that those languages have many bindings to useful off-the-shelf software. One of the reasons for the lack of such bindings in Ada is that the interface-to-other-languages features of Ada 83 are weak and very non-portable. Therefore, one of the main goals of Ada 9X is to provide the easiest possible interfaces to other languages. Although such interfaces can never be completely portable, we are trying to make them as portable as possible. In Ada 9X, one can apply pragma Import to a deferred constant. The pragma replaces the full_constant_declaration. This allows the import of read-only data into an Ada program -- an important capability. Obviously, any data type might be needed, and there is no particular reason that requires the data to be declared in a package. Deferred constants are important in child packages. A parent package might declare a private type, and a visible child package might need to export a constant of that type. That constant will need to be deferred, since the full_type_declaration is not visible in the visible part of the visible child. But the Ada 83 rule would make such a deferred constant illegal. One use for a deferred constant in Ada 9X is to export constant access to an (aliased) variable declared in the private part of a package: package P is type Table is array(...) of ...; type Table_Access is access constant Table; This_Table_Access: constant Table_Access; That_Table_Access: constant Table_Access; private This_Table: aliased Table := (...); This_Table_Access: constant Table_Access := This_Table'Access; That_Table: aliased Table := (...); That_Table_Access: constant Table_Access := That_Table'Access; end P; Now, the body of package P can change the tables, but clients of the package can only read them. ---------------- Except for the pragma Import example, all of the above uses for deferred constants can be done with functions. But if one suggests the use of functions, one has to question the need for any constants in Ada -- a function will always suffice. Constants exist in Ada because functions are so much more verbose when all you want is a simple constant object. Deferred constants are no different -- they are needed for the same reasons as normal constants, but they are used when, for one reason or another (as shown by the above examples), the initialization expression needs to see things that are not visible at the point of the (original) declaration of the constant. Requiring the user to write a function in such cases is the sort of annoyance that turns people away from a language. Furthermore, if the function is not inlined, then it is inefficient. If it IS inlined, then extra compilation dependences are added, possibly causing severe recompilation costs. And most implementations of inlining are still more costly than a reference to a constant. SUMMARY: Deferred constants are important for interfacing to other languages. They are also useful in various situations described above -- any situation in which the visibility of the constant declaration needs to be different from the visibility needed by the initialization expression. Functions cannot really replace deferred constants very well. And finally, deferred constants would be crippled in Ada 9X by the existence of a restriction inherited from Ada 83. Thus, the MRT recommends removal of the restriction.