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.