9 Namespaces
As in C++, namespaces are used to avoid name clashes in code. For
example:
namespace Foo {
int x = 0;
int f() { return x; }
}
declares an integer named Foo::x and a function named
Foo::f. Note that within the namespace, you don't need to use
the qualified name. For instance, Foo::f refers to
Foo::x as simply x. We could also simply write
``namespace Foo;'' (note the trailing semi-colon) and leave out
the enclosing braces. Every declaration (variables, functions, types,
typedefs) following this namespace declaration would be placed in the
Foo namespace.
As noted before, you can refer to elements of a namespace using the
``::'' notation. Alternatively, you can open up a namespace
with a ``using'' declaration. For example, we could follow the
above code with:
namespace Bar {
using Foo {
int g() { return f(); }
}
int h() { return Foo::f(); }
}
Here, we opened the Foo namespace within the definition of
Bar::g. One can also write ``using Foo;'' to open a
namespace for the remaining definitions in the current block.
Namespaces can nest as in C++.
Currently, namespaces are only supported at the top-level and you
can't declare a qualified variable directly. Rather, you have to
write a namespace declaration to encapsulate it. For example, you
cannot write ``int Foo::x = 3;.''
The following subtle issues and implementation bugs may leave
you scratching your head:
-
The current implementation translates qualified Cyclone
variables to C identifiers very naively: each :: is
translated to _ (underscore). This translation is wrong
because it can introduce clashes that are not clashes in Cyclone,
such as in the following:
namespace Foo { int x = 7; }
int Foo_x = 9;
So avoid prefixing your identifiers with namespaces in your program.
We intend to fix this bug in a future release.
- Because #include is defined as textual substitution, the
following are usually very bad ideas: Having ``namespace Foo;''
or ``using Foo;'' at the top level of a header file.
After all, you will be changing the identifiers produced or the
identifiers available in every file that includes the header file.
Having #include directives within the scope of namespace
declarations. After all, you are changing the names of the
identifiers in the header file by (further) qualifying them.
Unfortunately, the current system uses the C pre-processor before
looking at the code, so it cannot warn you of these probable errors.
In short, you are advised to not use the ``semicolon syntax'' in
header files and you are advised to put all #include
directives at the top of files, before any namespace or using
declarations.
- The translation of identifiers declared extern "C" is
different. Given
namespace Foo { extern "C" int x; }
the Cyclone code refers to the global variable as Foo::x, but
the translation to C will convert all uses to just x. The
following code will therefore get compiled incorrectly (f
will return 4):
namespace Foo { extern "C" int x; }
int f() {
int x = 2;
return x + Foo::x;
}