Classes and modules
static and dynamic classes, module, self, and importing files with use.
static class Person # called without "new"
dynamic class Animal # only with "new"
module Settings # a second name for static classdynamic class#
dynamic class Animal
$species as string
$age as int32
func __construct($species as string, $age as int32) as void
self.$species = $species
self.$age = $age
end func
func make_sound() as string
return "This is a " + self.$species
end func
func __destruct() as void
out("destroying: " + self.$species)
end func
end class$a = new Animal("dog", 3)
out($a.make_sound())The body holds only field declarations ($name as type) and functions. Free statements are not allowed — when they would run would be unclear.
Reaching a dynamic class member without new is an error.
static class and module#
module Settings
$port as int32
func address() as string
return "http://localhost:" + self.$port.to_string()
end func
end classout(Settings.$port)
out(Settings.address())If the constructor takes no parameters, a single instance is created when the file loads and its members are reached directly. If the constructor takes parameters there is no such instance; the class is only instantiated by calling it:
$p = Person("Ahmet", 25) # static class — no "new"self#
Inside methods, the instance itself. It cannot be used outside a method.
Importing files#
use "/lib/site.lx" as site
use "helper.lx" # without "as", the package name is used| Path | Resolved against |
|---|---|
"/a/b.lx" | the project root — the directory of the entry file |
"b.lx" | the containing file — the file next to it |
The distinction is deliberate: a root-relative path stays correct when the file moves, and a relative path is short for neighbouring files.
$p = classes.Person("Ahmet", 25)
$a = new classes.Animal("Dog", 3)
out(functions.add(5, 10))Scope#
An imported file runs in its own scope: it does not see the caller's variables and cannot change them. Only exported classes and functions enter the namespace — variables are not shared.
This decision shapes how the language carries state. You cannot keep a module-level "which language are we in" variable; that information either travels as a parameter or lives in $app.globals.
An imported function or class method sees the names of its own file, not the caller's.
Even if the same file is imported several times in one run, it runs once — its side effects, such as opening a connection, should not repeat. Circular imports are an error.
Exporting#
Classes whose names start with a capital letter are exported.
External libraries#
use_lib jwtComing in phase 2; today it raises an error saying which phase it is in. Quoted use is in-project, use_lib is out-of-project — where a name comes from is visible as you read.