Back: Memory access
Up: Features
Forward: 3.2.1 Introduction
 
Top: GNU Smalltalk User's Guide
Contents: Table of Contents
Index: Class index
About: About this document

3.2 Namespaces

[This section (and the implementation of namespaces in GNU Smalltalk) is based on the paper Structured Symbolic Name Spaces in Smalltalk, by Augustin Mrazik.]


3.2.1 Introduction

The standard Smalltalk-80 programming environment supports symbolic identification of objects in one global namespace--in the Smalltalk system dictionary. This means that each global variable in the system has its unique name which is used for symbolic identification of the particular object in the source code (e.g. in expressions or methods). Most important global variables are classes defining the behavior of objects.

In a development dealing with modelling of real systems, polymorphic symbolic identification is often needed. This means that it should be possible to use the same name for different classes or other global variables. Let us mention class Module as an example which would mean totaly different things for a programmer, for a computer technician and for a civil engineer or an architect.

This issue becomes inevitable if we start to work in a Smalltalk environment supporting persistence. Polymorphism of classes becomes necessary in the moment we start to think about storing classes in the database since after restoring them into the running Smalltalk image a mismatch with the current symbolic identification of the present classes could occur. For example you might have the class Module already in your image with the meaning of a program module (e.g. in a CASE system) and you might attempt to load the class Module representing a part of the computer hardware from the database for hardware configuration system. The last class could get bound to the #Module symbol in the Smalltalk system dictionary and the other class could remain in the system as unbound class with full functionality, however, it could not be accessed anymore at the symbolical level in the source code.

Objects which have to be identified in the source code of methods or message sends by their names are included in Smalltalk which is a sole instance of SystemDictionary. Such objects may be identified simply by stating their name as primary in a Smalltalk statement. The code is compiled in the Smalitalk environment and if such a primary is found it is bound to the corresponding object as receiver of the rest of the message send. In this way Smalltalk as instance of SystemDictionary represents the sole symbolic name space in the Smalltalk system. In the following text the symbolic name space will be called simply environment to make the text more clear.


3.2.2 Concepts

To support polymorphic symbolical identification several environments will be needed. The same name may be located concurrently in several environments and point to diverse objects.

However, symbolic navigation between these environments is needed. Before approaching the problem of the syntax to be implemented and of its very implementation, we have to point out which structural relations are going to be established between environments.

Since the environment has first to be symbolically identified to gain access to its global variables, it has to be a global variable in another environment. Obviously, Smalltalk will be the first environment from which the navigation begins. From Smalltalk some of the existing environments may be seen. From these environments other sub-environments may be seen, etc. This means that environments represent nodes in a graph where symbolic identifications from one environment to another one represent branches.

However, the symbolic identification should be unambiguous although it will be polymorphic. This is why we should avoid cycles in the environment graph. Cycles in the graph could cause also other problems in the implementation, e.g. unability to use recursive algorithms. This is why in general the environments build a directed acyclic graph(3).

Let us call the partial ordering relation which occurs between the two environments to be inheritance. Sub-environments inherits from their super-environments.

Not only that "inheritance" is the standard term for the partial ordering relation in the lattice theory but the feature of inheritance in the meaning of object-orientation is associated with this relation. This means that all associations of the super-environment are valid also in its sub-environments unless they are locally redefined in the sub-environment.

A super-environment includes all its sub-enviroments as associations under their names. The sub-environment includes its super-environment under the symbol #Super. Most environments inherit from Smalltalk, the standard root environment, but they are not required to do so; this is similar to how most classes derive from Object, yet one can derive a class directly from nil. Since they all inherit from Smalltalk all global variables defined in it, it is not necessary to define a special global variable pointing to root in each environment.

The inheritance links to the super-environments are used in the lookup for a potentially inherited global variable. This includes lookups by a compiler searching for a variable and lookups via methods such as #at: and #includesKey:.


3.2.3 Syntax

Global objects of an environment (local or inherited) may be referenced by their symbol used in the source code, e.g.
 
            John goHome

if the #John -> aMan association exists in the particular environment or one of its super-environments, all along the way to the root environment.

If an object has to be referenced from another environment (i.e. which is not on the inheritance link) it has to be referenced either relatively to the position of the current environment (using the Super symbol), or absolutely (using the "full pathname" of the object, navigating from Smalltalk through the tree of sub-environments).

For the identification of global objects in another environment a "pathname" of symbols is used. The symbols are separated by blanks, i.e. the "look" to be implemented is that of
 
Smalltalk Tasks MyTask

and of
 
Super Super Peter.

Its similarity to a sequence of message sends is not casual, and suggests the following syntax for write access:(4)
 
Smalltalk Tasks MyTask: anotherTask

This resembles the way accessors are used for other objects. As it is custom in Smalltalk, however, we are reminded by uppercase letters that we are accessing global objects.

In addition, a special syntax has been implemented that returns the Association object for a particular global: so the last example above can be written also like
 
#{Smalltalk.Tasks.MyTask} value: anotherTask

This special kind of literal (called a variable binding) is also valid inside literal arrays.


3.2.4 Implementation

A superclass of SystemDictionary called RootNamespace has to be defined and many of the features of Smalltalk-80 SystemDictionaries will be hosted by that class. Namespace and SystemDictionary will in turn become subclasses of RootNamespace. One could wonder why is RootNamespace superior to Namespace in the hierarchy: the answer is that it is more convenient because root namespaces are more similar to Dictionaries, not having to handle the burden of lookup into super-environments.

To handle inheritance, the following methods have to be defined or redefined in Namespace (not in RootNamespace):

Accessors like #at:ifAbsent: and #includesKey:
Inheritance has to be implemented.

Enumerators like #do: and #keys
This should return all the objects in the namespace, including those which are inherited.

For programs to be able to process correctly the "pathnames" and the accessors, this feature must be implemented directly in RootNamespace; it is easily handled through the standard doesNotUnderstand: message for trapping message sends that the virtual machine could not resolve. RootNamespace will also implement a new set of methods that allow one to navigate through the namespace hierarchy; these parallel those found in Behavior for the class hierarchy.

The most important task of the Namespace class is to provide organization for the most important global objects in the Smalltalk system--for the classes. This importance becomes even more crucial in the structured environments which is first of all a framework for class polymorphism.

In Smalltalk the classes have the instance variable name which holds the name of the class. Each defined class is included in Smalltalk under this name. In a framework with several environments the class should know the environment in which it has been created and compiled. This is a new variable of Class which has to be defined and properly set in relevant methods. In the mother environment the class should be included under its name.

Of course, any class (just like any other object) may be included concurrently in several environments, even under different symbols in the same or in diverse environments. We can consider this 'alias names' of the particular class or global variable. However, classes may be referenced under the other names or in other environments as their mother environment e.g. for the purpose of intance creation or messages to he class (class methods), but they cannot be compiled in other environment. If a class compiles its methods it always compiles them in its mother environment even if this compilation is requested from another environment. If the syntax is not correct in the mother environment, a compilation error simply occurs.

An important issue is also the name of the class answered by the class for the purpose of its identification in diverse tools (e.g. in a browser). This has to be change to reflect the environment in which it is shown, i.e. the method `nameIn: environment' has to be implemented and used on proper places.

These methods are not all which have to redefined in the Smalltalk system to achieve full functionality of structured environments. In particular, changes have to be made to the behavior classes, to the user interface, to the compiler, to a few classes supporting persistance. An interesting point that could not be noticed is that the environment is easier to use if evaluations (doits) are parsed as if UndefinedObject's mother environment was the current namespace.


3.2.5 Using namespaces

Using namespaces if often merely a matter of rewriting the loading script this way:
 
    Smalltalk addSubspace: #NewNS!
    Namespace current: NewNS!
    ...
    Namespace current: Smalltalk!

Also remember that pool dictionaries are actually "pool namespaces", in the sense that including a namespace in the pool dictionaries list will automatically include its superspaces too. Declaring a namespace as a pool dictionaries is similar in this way to C++'s using namespace declaration.

Finally, be careful when working with fundamental system classes. Although you can use code like
 
    Smalltalk Set variableSubclass: #Set
        ...
        category: 'My application-Extensions'

or the equivalent syntax Set extend, this approach won't work when applied to core classes. For example, you might be successful with a Set or WriteStream object, but subclassing SmallInteger this way can bite you in strange ways: integer literals will still belong to the Smalltalk dictionary's version of the class (this holds for Arrays, Strings, etc. too), primitive operations will still answer standard Smalltalk SmallIntegers, and so on. Or, variableWordSubclasses will recognize 32-bit Smalltalk LargeInteger objects, but not LargeIntegers belonging to your own namespace.

Unfortunately this problem is not easy to solve since Smalltalk has to cache the OOPs of determinate class objects for speed--it would not be feasible to lookup the environment to which sender of a message belongs every time the + message was sent to an Integer.

So, GNU Smalltalk namespaces cannot yet solve 100% of the problem of clashes between extensions to a class--for that you'll still have to rely on prefixes to method names. But they do solve the problem of clashes between class names and pool dictionary names, so you might want to give them a try. An example of using namespaces is given by the `examples/Publish.st' file in the GNU Smalltalk source code directory.




This document was generated on May, 12 2002 using texi2html