Next Previous Contents

10. Namespaces

By default, all global variables and functions are defined in the global or public namespace. In addition to the global namespace, every compilation unit (e.g., a file containing S-Lang code) has a private, or anonymous namespace. The private namespace is used when one wants to restrict the usage of one or more functions or variables to the compilation unit that defines them without worrying about objects with the same names defined elsewhere.

Objects are declared as belonging to the private namespace using the private declaration keyword. Similarly if a variable is declared using the public qualifier, it will be placed in the public namespace. For example,

    private variable i;
    public variable j;
defines a variable called i in the private namespace and one called j in the public namespace.

The implements function may be used to create a new namespace of a specified name and have it associated with the compilation unit. Objects may be placed into this namespace space using the static keyword, e.g.,

    static variable X;
    static define foo () {...}
For this reason, such a namespace will be called the static namespace associated with the compilation unit. Such objects may be accessed from outside the local compilation unit using the namespace operator -> in conjunction with the name of the namespace.

Since it is possible for three namespaces (private, static, public) to be associated with a compilation unit, it is important to understand how names are resolved by the parser. During the compilation stage, symbols are looked up according to the current scope. If in a function, the local variables of the function are searched first. Then the search proceeds with symbols in the private namespace, followed by those in the static namespace associated with the compilation unit (if any), and finally with the public namespace. If after searching the public namespace the symbol has not been resolved, an UndefinedNameError exception will result.

In addition to using the implements function, there are other ways to associate a namespace with a compilation unit. One is via the optional namespace argument of the evalfile function. For example,

    () = evalfile ("foo.sl", "bar");
will cause foo.sl to be loaded and associated with a namespace called bar. Then any static symbols of foo.sl may accessed using the bar-> prefix.

It is important to note that if a static namespace has been associated with the compilation unit, then any symbols in that unit declared without an namespace qualifier will be placed in the static namespace. Otherwise such symbols will be placed in the public namespace, and any symbols declared as static will be placed in the private namespace.

To illustrate these concepts, consider the following example:

   % foo.sl
   variable X = 1;
   static variable Y;
   private variable Z;
   public define set_Y (y) { Y = y; }
   static define set_z (z) { Z = z; }
If foo.sl is loaded via
    () = evalfile ("foo.sl");
then no static namespace will be associated with it. As a result, X will be placed in the public namespace since it was declared with no namespace qualifier. Also Y and set_z will be placed in the private namespace since no static namespace has been associated with the file. In this scenario there will be no way to get at the Z variable from outside of foo.sl since both it and the function that accesses it (set_z) are placed in the private namespace.

On the other hand, suppose that the file is loaded using a namespace argument:

    () = evalfile ("foo.sl", "foo");
In this case X, Y, and set_z will be placed in the foo namespace. These objects may be accessed from outside foo.sl using the foo-> prefix, e.g.,
    foo->set_z (3.0);
    if (foo->X == 2) foo->Y = 1;

Because a file may be loaded with or without a namespace attached to it, it is a good idea to avoid using the static qualifier. To see this, consider again the above example but this time without the use of the static qualifier:

    % foo.sl
    variable X = 1;
    variable Y;
    private variable Z;
    public define set_Y (y) { Y = y; }
    define set_z (z) { Z = z; }
When loaded without a namespace argument, the variable Z will remain in the private namespace, but the set_z function will be put in the public namespace. Previously set_z was put in the private namespace making both it and Z inaccessible.


Next Previous Contents