Namespace
Namespaces provide essential structure and clarity to your Rell projects, allowing for better organization and modularization of code.
Namespaces have the following characteristics:
- Simplified referencing: Within a namespace, you can use identifiers directly without specifying the full name. For
example, use
countryinstead offoo.countrywhen inside thefoonamespace. - Qualified table names: Tables for entities and objects defined in a namespace include the full namespace path in
their names. For instance, the table for entity
foo.useris namedc0.foo.user. - Multiple definitions: You can define a namespace with the same name multiple times, each with different inner definitions, allowing for distributed declarations across files.
Basic namespace usage
namespace foo {
entity user {
name;
country;
}
struct point {
x: integer;
y: integer;
}
enum country {
USA,
DE,
FR
}
}
query get_users_by_country(c: foo.country) = foo.user @* { .country == c };
Anonymous namespaces
Anonymous namespaces allow for focused organization or applying annotations to a group of definitions without creating a named namespace.
Example
namespace {
// some definitions
}
You can use it to apply an annotation to a set of definitions:
@mount('foo.bar')
namespace {
entity user {}
entity company {}
}
Nested namespaces
Create hierarchical structures using nested namespaces for fine-grained organization. You can use nested namespaces for complex projects with multiple layers of organization.
Short notation:
namespace x.y.z {
function f() = 123;
}
Equivalent expanded notation:
namespace x {
namespace y {
namespace z {
function f() = 123;
}
}
}
Splitting namespaces across files
For improved modularity, you can distribute namespace members across multiple files within a module. When splitting namespaces across files, ensure consistent naming and organization.
Example
// lib/a.rell
namespace ns {
function f(): integer = 123;
}
// lib/b.rell
namespace ns {
function g(): integer = 456;
}
// main.rell
import .lib;
function main() {
print(lib.ns.f()); // Outputs: 123
print(lib.ns.g()); // Outputs: 456
}
Anonymous imports
Anonymous imports allow you to activate a module without adding it to the current namespace. Use the special alias _
for anonymous imports.
Anonymous imports make a module active, enabling its operations, queries, function extensions, and overrides—the same way as normal imports. However, there is no way to access the module from code (as it has no alias), and no names are added to the namespace.
Example
import _: foo;
import _: bar;
In this example, both foo and bar modules are activated, but they cannot be accessed directly in the code since they
have no alias. Their operations, queries, function extensions, and overrides are still available and active.