Expressions
Precedence
Section titled “Precedence”From tightest to loosest binding. All binary operators are left-associative except ?? (right) and the
ternary ? :.
| Level | Operators |
|---|---|
| primary | literals · names · (…) · f(…) · .member · [index] · T { … } · new T { … } · .case(…) |
| postfix | expr? (try-unwrap) · ?.member (null-conditional) · with { … } |
| unary | ! not · unary - · & (address-of) · * (deref / by-ref) |
| multiplicative | * / % |
| additive | + - |
| range | .. |
| comparison | < <= > >= |
| equality | == != |
| logical and | && and |
| logical or | || or |
| null-coalescing | ?? |
| ternary | ? : |
(Assignment and compound assignment are statements, not expressions.)
Grammar
Section titled “Grammar”Expr = Coalesce [ "?" Expr ":" Expr ] . // ternaryCoalesce = OrExpr { "??" OrExpr } .OrExpr = AndExpr { ( "||" | "or" ) AndExpr } .AndExpr = Equality { ( "&&" | "and" ) Equality } .Equality = Comparison { ( "==" | "!=" ) Comparison } .Comparison = Range { ( "<" | "<=" | ">" | ">=" ) Range } .Range = Additive [ ".." Additive ] .Additive = Multiplicative { ( "+" | "-" ) Multiplicative } .Multiplicative = Unary { ( "*" | "/" | "%" ) Unary } .Unary = ( "!" | "not" | "-" | "&" | "*" ) Unary | Postfix .Postfix = Primary { Selector } .Selector = "." identifier // member access | "(" [ ArgList ] ")" // call | "<" TypeList ">" "(" [ ArgList ] ")" // generic call | "[" Expr "]" // index | "?" // try-unwrap | "?." identifier // null-conditional | "with" "{" FieldInitList "}" . // non-destructive updatePrimary = literal | identifier | "(" Expr { "," Expr } ")" // parenthesised / tuple | CompositeLit | NewExpr | ListLit | DotCase | Lambda | MatchExpr | "ok" "(" Expr ")" | "error" "(" Expr ")" | "await" Unary | "spawn" Block .CompositeLit = TypeName [ TypeArgs ] "{" [ FieldInitList ] "}" .FieldInitList = FieldInit { ( "," | newline ) FieldInit } .FieldInit = identifier ":" Expr .NewExpr = "new" TypeName ( "{" [ FieldInitList ] "}" | "(" [ ArgList ] ")" ) .ListLit = "[" [ Expr { "," Expr } ] "]" .DotCase = "." identifier [ "(" [ ArgList ] ")" ] .Lambda = "func" "(" [ ParamList ] ")" [ ReturnType ] ( Block | "=" Expr ) | "(" [ identifier { "," identifier } ] ")" "=>" Expr .ArgList = Arg { "," Arg } .Arg = [ "out" | "&" | "*" ] Expr .Semantics (selected)
Section titled “Semantics (selected)”Try-unwrap expr?. If expr is a Result, ? yields the ok value or returns the error from the
enclosing function. It is an expression operator — valid anywhere an expression appears (a let, a
return, a call argument, a bare statement). The enclosing function’s error type shall be compatible. The
spelling expr?.member parses as the null-conditional operator; to unwrap-then-access, parenthesise
((expr?).member) or bind with a let. See Errors.
Ternary vs. try-unwrap. ? is disambiguated by lookahead: if the next token can begin an expression,
? is the ternary operator; otherwise it is postfix try-unwrap.
Null-coalescing a ?? b yields a if non-null, else b. Null-conditional a?.m yields a.m if
a is non-null, else null/default; it chains (a?.b?.c).
Composite literal T { f: v } constructs a value of type T; field initializers are comma- or
newline-separated. new T { … } / new T(…) heap-allocates a value data and yields *T — the only
allocation expression; new on a non-data type is ES2144, on a ref data
is ES2003.
Address-of &x yields a managed pointer to a variable, or a function pointer for a function name;
*x / &x at a call site pass by reference. See Pointers & by-ref.
.case / ok / error construct a choice variant or a
Result side when the target type is known from context.
Collection literal [a, b] constructs a List<T> with T inferred from the elements; [] is
List<object>. A parenthesised comma list (a, b) constructs a ValueTuple.
Lambdas. func(…) -> T { … } and the arrow form (x) => expr are function literals; arrow-parameter
types are inferred when a delegate type is expected. Both close over the enclosing scope; captures are
mutable, and a closure over a let may read but not write it.
match as an expression appears in any expression position; every arm produces a value of one common
type. Its grammar is given with the statement form.