Silex v0.47.1 / Docs Canonical source ↗

Find a syntax form

Use this page as a quick index. Follow a concept link to understand its behavior and constraints.

Intention Form
Immutable variable let name:type = value
Mutable variable var name:type = value
Recommended line comment // comment
Alternate line comment # comment
Block comment /* comment */
String "text"
Block string " followed by indented lines and a " alone on its line
Interpolation "value: $(expression)"
Function func name(value:type) ReturnType { ... }
Named call name(value:expression)
Mixed call name(expression, other:expression)
Structure struct Name { ... }
Class class Name { ... }
Non-clonable class nocopy class Name { ... }
Compiler-provided contract intrinsic class Name { ... }
Protocol protocol Name { ... }
Read-only property let name:type { get { ... } }
Initialized property var name:type = value { get { ... } }
Property with implicit setter var name:type { get { ... } }
Property with explicit setter var name:type { get { ... } set(value) { ... } }
Property requirement name:type { get } or name:type { get set }
Extension extend Name { ... }
Catalog contribution contribute GFX.Components { public use GFX.Physics.RigidBody2D.RigidBody2D }
Enum variant caseName(Type) inside an enum
Variant without content Enum.caseName
Variant with content Enum.caseName(value)
Ignored match content caseName(_)
Guarded branch caseName(value) if condition => result
Literal pattern 200 => result, "stop" => result, or true => result
Ordered conditions match { condition => value; else => fallback }
match block value pattern => { ...; yield value }
Safe optional assignment optional?.field = value
Forced optional extraction optional!
Optional fallback optional ?? fallback
Constructor init(value:type) { ... }
Global package import use STD.UUID
Package-anchored import use Package.UUID
Current-directory import use Module.UUID
Package-qualified path Package.UUID.Value
Directory-qualified path Module.UUID.Value
C function binding let name = C.function<func(...) Return>(...)
C address call C.call<func(...) Return>(address, ...)
Alias use Existing.Type as LocalName
Public declaration public ...
Package declaration package ...
Module declaration module ...
File declaration local ...
Optional Type?
Nested optional Type??
Named tuple (width:int, height:int)
Positional tuple (int, int)
Borrowed tuple pattern (@Velocity, &Transform)
Tuple destructuring let (first, second) = value
Fixed array Type[3]
Dynamic list Type[]
Shared view @Type[..]
Mutable view &Type[..]
Read parameter value:@Type
Mutable parameter value:&Type
Detached copy copy value
Transfer move value
Checked conversion value as Type
Success propagation try operation()
Critical section mutex { ... }
Method cascade value..update()
Bound instance method receiver.method
Reflection reflect(value)
Cascade assignment value..field = replacement

match is a control word in expression position, but remains contextual after func, ., ?., or ... A method may therefore naturally be named match: func match(...) and pattern.match(text).

move is also contextual after func, ., ?. and ..: a method may be named move, as in actor.move(displacement). In prefix position, move value retains its ownership-transfer meaning. Use an explicit receiver when calling a method with this name.

Primitive type spellings are likewise contextual as method names. A type API can declare static func float32() and be called with DType.float32() without making float32 available as an ordinary identifier.

in remains the iteration word, but becomes contextual as a variant name, in a match branch, and after . or ?.: Easing.in is valid.

The ?, [], and [N] suffixes apply from left to right. Type?[] and Type[]? are therefore different types.

Statements and scopes

if condition {
} elif other {
} else {
}

while condition {
    break
    continue
}

for value in collection {
}

for index, value in collection.indexed() {
}

for value in start...end {
}

mutex {
    update_shared_state()
}

{
    let temporary = prepare()
    consume(temporary)
}

return value
yield value // only as the direct final statement of a value-match branch block
print(value)
assert(condition)
assert(condition, "message")
panic("message")

A bare block is an anonymous lexical scope, not an expression. It runs once, has no trailing semicolon, hides its variables after }, and cleans them up before any normal or transferred exit. break and continue always target the nearest enclosing loop.

Operator precedence

From strongest to weakest binding:

as
-  !  try  copy  move
*  /  %
+  -
<<  >>
&
^
<  <=  >  >=
==  !=
&&
||
..method(...)  ..field = value

The .. cascade binds less strongly than ordinary operators. A single dot after a method segment resumes ordinary access on that method's result. The ... range remains a different token from ...

A statement ends at a line break, before }, or with ;. Two statements on the same line require a semicolon.

Operator declarations

[visibility] func operator + (left:T, right:U) R { ... }
[visibility] func operator - (value:T) R { ... }

The declarable symbols are +, -, *, and /. A declaration appears at module level, uses one value parameter for negation or two for a binary operation, and returns a non-void owned value. Defaults, references, and generic type parameters are not accepted. At least one nominal operand type belongs to the declaring package.

A C.function binding is the only module-level let accepted in Silex 0.44. See interoperability for its exact signature and lifetime.

Back to the reference