keithro@microsoft.UUCP (Keith ROWE) (05/03/91)
I submitted a paper at the last ANSI X3J16 meeting on the subject of name space pollution. It is quite similar to some of the discussion I have seen here recently. I have included an electronic version of this paper here for your comments. I plan to submit a revised version of this paper at the June meeting. Please send me any comments or suggestions you may have. thanks, Keith Rowe uunet!microsoft!keithro ----- cut here ----- ANSI X3J16/91-0041 Name Space Pollution: A Proposal Version 1: Feb 4, 1991 Version 2: March 9, 1991 Keith Rowe Microsoft Corp. uunet!microsoft!keithro 1.0 The Problem One of the goals of C++ is to encourage the re-use of code. As this practice becomes more common, more and more of our code will be pieced together from previously written components. The problem is that groups of classes from different authors may inadvertently select identical symbol names for classes, enumerations, member functions and objects that may act very differently. The likelihood of such a name clash grows exponentially with the number of authors contributing to the new work. This problem will affect both those who try to generate classes for re-use and those who try to combine the classes again. 1.1 An Example Vendor A creates a hierarchy of classes for window management and decides to model a list box with a class called List. Vendor B creates a second hierarchy of classes to handle collections and decides to model sequentially ordered collection with a class called List. Even though these two sets of classes may complement each other well, the re-use of the name List will make it very difficult to combine these classes or even to use them in the same application. If the consumer of the classes doesn't have access to the source code for the classes, it may even be impossible. What we need is a convention, mechanism or combination of the two that allows authors to prevent symbol collisions between their groups of classes. This should be easy to use and minimize the inconvenience to the consumer of the classes. 2.0 Rejected Solutions One approach would be to suggest a convention where all vendors use a unique prefix for all their symbol names. The X Windows and Motif libraries are examples of this solution. While this is a simple solution that requires no change in the language, it does require awkward symbol names. Will users of your class always want to type MS before every symbol? Also, there is no guarantee that two vendors may not accidentally choose identical prefixes. This will be compounded by the natural drive to keep prefixes short. For example, what keeps Michigan State and Microsoft from both choosing to append MS to all their symbols? 3.0 "Bundle" and "Use" A bundle is a group of declarations that share a common named scope, much like nested classes. Bundles are neither types nor classes, and thus, instances of a bundle cannot be created. Bundles can be nested within other bundles. Individual declarations within a bundle can be accessed using the existing notation for nested classes. The syntax for declaring a bundle is: bundle identifier { declaration-list } For example: bundle Microsoft { class Window { // class declaration // ... }; int windowCount; // type declaration void tallyWindows(Window w) // regular function { //... }; }; main () { Microsoft::Window myWindow; Microsoft::windowCount = 1; Microsoft::tallyWindows(myWindow); } This provides authors with a convenient mechanism for uniquely marking their class libraries. Since full identifiers are used to name bundles, it is convenient use long strings that cannot conflict (company names or modified internet addresses, for example). Since bundles can be nested, various groups within a larger project can also protect their name spaces (eg. the windowing team can use Microsoft::Windows and the spreadsheet team can use Microsoft::Excel). The mechanism of using the '::' operator to distinguish scopes is already used in C++. The chief drawback of this addition is the long symbol identifiers that the consumer of the class library must now use. This is solved with the use keyword. The statement: use bundle-identifier; can be introduced at any scope in a function definition or at global scope. From that point on in the current scope, any identifier that cannot be found in the symbol table is tried again with the bundle identifier prefixed to it. Multiple use statements can be active and the bundles are checked in order from the most recently declared use statement to the least recently declared. For example: bundle Microsoft { // same as previous example }; main() { use Microsoft; // These statements are equivalent to those in the // previous example. Window myWindow; windowCount = 1; tallyWindow(myWindow); } Now the '::' operator is only needed in those cases where a symbol is used in two bundles. For example: bundle VendorA { class List { /* List Box stuff */ }; }; bundle VendorB { class List { /* Seq Ordered collection stuff */ }; }; void organizeMenus () { VendorB::List mylist; VendorA::List * menu; // ... } 4.0 Summary Name pollution will become a serious problem for the C++ programmers of tomorrow. Organizing libraries of classes into bundles will keep the name spaces uniquely identifiable and, with the use statement, will not burden the consumer of these libraries with awkward notation. I would like to thank Martin O'Riordan for his valuable input to this proposal.
aed@netcom.COM (Andrew Davidson) (05/08/91)
In article <72143@microsoft.UUCP> keithro@microsoft.UUCP (Keith ROWE) writes: > >4.0 Summary > >Name pollution will become a serious problem for the C++ programmers of >tomorrow. Organizing libraries of classes into bundles will keep the >name spaces uniquely identifiable and, with the use statement, will not >burden the consumer of these libraries with awkward notation. > Is this really a problem the language neededs to support. You mentioned that this problem can be solved by convention. Also why is this not concidered a problem in C or other programming langs that support libraries? If it is a concidered a problem in other langs, what mechnism do these langs use to solve the problem. Thanks Andy -- ----------------------------------------------------------------- "bede-bede-bede Thats all Folks" Porky Pig Andy Davidson Woodside CA. aed@netcom.COM -----------------------------------------------------------------
garry@ithaca.uucp (Garry Wiegand) (05/14/91)
In a recent article keithro@microsoft.UUCP (Keith ROWE) wrote: >main() >{ > use Microsoft; [a number of statements] > tallyWindow(myWindow); >} A few comments. The "use Microsoft" statement in the above is sort of weird - it looks like it might be a declaration statement, but "use" is an active verb and for me makes the statement look more like an executable. Also, the style is perhaps surprise-inducing - "use Microsoft" is an innocuous-looking statement buried among others but it has unusually subtle and drastic effects. It makes me think of #include's and goto's. I don't know if this has been discussed, but how about the traditional (in Algol/Pascal/PL1/etc worlds) 'with' construct instead? The C/C++ version would be something like: with (blah) { } meaning "please try to disambiguate the names in this block in favor of the 'blah' context". The classical example of this style is structure references - the following simple code: struct {float x,y;} *vector; ... cout << "Length is" << sqrt(vector->x*vector->x + vector->y*vector->y); would also be expressable as: struct {float x,y;} *vector; ... with (*vector) { cout << "Length is" << sqrt (x*x + y*y); } (or of course:) with (*vector) cout << "Length is" << sqrt (x*x + y*y); The block would follow the usual scoping conventions. The wonderful C++ disambiguation rules would have to be worked out. The syntax for Keith's case would be "with (Microsoft) { }". There is an example of the concept already in the language: method bodies behave exactly as if they were surrounded by a "with (*this) { }". It would be nice to have it available for things other than "*this". (I admit that if you can write your class definitions real cleanly you might scarcely *need* it for cases other than "*this".) So: I agree that C++ names are getting complicated, and I claim that a new general construct that could help you organize the name references would be a good thing to have. In particular, a 'with' would get you more value for your syntactic money than a 'use' because it would also be meaningful for structure references and for all types of '::' references. It would offer a reasonable hint to the compiler that when the appropriate the operand might be worth optimizing into a register. The 'Name::' dereferencing Keith needed would come almost for free as part of a more general concept. Garry Wiegand --- Ithaca Software, Alameda, California ...!uunet!ithaca!garry, garry%ithaca.uucp@uunet.uu.net