A Guide to the S-Lang Language: Namespaces

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 `get_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