Namespaces
A file can scope all of its declarations under a namespace with a single declarator on its first line:
namespace File;
bool exists(string path) {
return File.size(path) != null;
}Everything declared in the file (functions, types, constants, global
variables) is then only visible through the qualified name:
File.exists, File.Error,
File.read. There is no fallback: unqualified
exists does not find File.exists, not even
inside the namespace's own files. Qualify every use, including calls
between members of the same namespace.
Callers use the same syntax for every member kind:
void main() {
if File.exists("notes.txt") {
println("found it");
}
var size = File.size("notes.txt");
println(size == null);
}Types work the same way, including in annotations and generic arguments:
void main() {
File.Error? error = null;
Result<string, File.Error> result = Err(File.Error.CouldNotOpen);
println(error == null);
println(result == Err);
}A namespace can span files: every file with the same declarator adds to the same namespace. Nest with dots:
namespace Outer.Inner;
int helper() {
return 1;
}
int deep() {
return Outer.Inner.helper();
}Name collisions and precedence
A namespace root must not collide with a top-level declaration name
in the same module: with namespace File; in the module,
declaring struct File is an error. For the same reason,
types and functions take precedence when both could match
a.b; values never hide a namespace, so a parameter named
path does not break Path.join calls.
The standard library names its namespaces in PascalCase:
File, Path, Json. A qualified
call then reads like a static method call (Path.join(...)),
and never confuses the reader the way path.join(path)
would, with the same spelling meaning two different things on one
line.
Declarations that stay global
Two declarations stay global even in a namespaced file, because
lookup for them is global: extern declarations name C
symbols, which have no namespaces, and operator overloads resolve
through global lookup. The main function must be global
too: declaring it inside a namespace is an error.
The standard library scopes its crowded areas this way:
File.exists, etc. Most of the standard library stays global
(List, println); namespaces are for groups of
related declarations that would otherwise claim generic names.
private works as usual: it restricts a declaration to its
module, qualified or not.