Define static members and containers
A static member belongs to the type itself. Always select it with the full
type name, never with an instance.
struct Position {
var x:int
static let tile_width:int = 32
static func origin() Position {
return Position()
}
}
func main() {
let origin = Position.origin()
print(origin.x)
}
A class accepts the same static members. They are neither inherited nor dynamically dispatched.
A static property may initialize its own storage on the first read, notably to express a singleton without a second cache field.
Create a container without instances
Declare static struct or static class when a type exists only to qualify
constants, shared state, or operations:
public static struct Constants {
let canvas_width:int = 960
let canvas_height:int = 640
func area() int {
return Constants.canvas_width * Constants.canvas_height
}
}
All fields and methods become implicitly static. Canonical style therefore
omits static on each one; the redundant modifier remains accepted for source
compatibility.
A static container cannot be constructed and has no constructor, self,
drop, base class, protocol conformance, protected member, extension, or
type parameters of its own. Its methods may still declare their own type
parameters. Ordinary nested structures and classes remain constructible unless
their own declaration is also marked static.
Initialize at compile time
Silex chooses the strategy according to the value, independently of let or
var. A statically representable value is evaluated entirely at compile time.
It may use intrinsic literals, operators, numeric conversions, immutable static
fields, functions proven to be compile-time evaluable, and similarly proven
constructors of value structures whose fields are themselves static.
struct Vec2 {
var x:float
var y:float
init(x:float, y:float) {
self.x = x
self.y = y
}
}
static struct Waypoints {
let first:Vec2 = Vec2(-200.0, 200.0)
let second:Vec2 = Vec2(200.0, 200.0)
}
The constructed value is stored directly in the program's static data.
Reading Waypoints.first produces a copy and does not call its constructor
again at runtime.
A compile-time evaluated function uses only intrinsic scalars, immutable local
variables, and other compile-time evaluable calls. This path cannot read a
static var, produce an effect, allocate a runtime resource, or form a
dependency cycle.
Initialize before main
An owned dynamic list requires runtime storage. Silex then generates an
initializer executed before main or before an isolated test entry:
static struct Paths {
let triangle:int[] = [1, 2, 3]
var editable:int[] = [0]
}
let makes the static field immutable without requiring its value to live in
binary data. Paths.triangle may be read, indexed, and traversed, but neither
reassigned nor resized. var allows reassignment and list mutations such as
Paths.editable.append(4).
Runtime static fields are initialized once, in declaration order. An
initializer may read a runtime field declared earlier; reading its own field or
a later field is rejected. Their owned storage remains alive throughout the
program or isolated test session. On a normal return from main or the test
entry, Silex releases owned static values after local values, in reverse field
declaration order. This includes objects held in an optional static cache.
Fields that share the same object each release their reference; the object is
destroyed when its last reference is released.
The values currently accepted on this runtime path are owned dynamic lists and value structures that contain them.