Variables and Constants
Variable Declarations
Section titled “Variable Declarations”Variables are mutable by default. The mut keyword is accepted but optional:
do compute() -> (i64, Error) { return 1, nil }
do main() { mut a i64 = 42 // mutable b i64 = 42 // mutable (default, `mut` is optional) name = "hello" // mutable, type inferred result, err = compute() // mutable, multi-return inferred println(a) println(b) println(name) println(result)}Variables declared this way:
- Can be reassigned after declaration
- Are scoped to their containing block
A declaration with a type annotation but no value is allowed and zero-initializes the variable (0, 0.0, "", false, and so on). Because a dropped = value is easy to miss, the compiler emits W1004 in that case:
do main() { count i64 // warning[W1004]: 'count' declared with no value — defaults to 0 total i64 = 0 // no warning; the zero value is explicit println(count) println(total)}Like all warnings, W1004 can be suppressed with -q W1004 or -q all. const declarations must always have a value (E2011).
Constant Declarations
Section titled “Constant Declarations”Constants are declared using the const keyword:
const Point struct { x i64 y i64}
const PI f64 = 3.14159const MAX_SIZE i64 = 100const origin = Point{x: 0, y: 0}
do main() { println(PI) println(MAX_SIZE) println(origin)}At file scope, const declarations of primitive types (integer and float types, string, bool, char) and arrays require explicit type annotations. Struct literals and enum values can still be inferred. Inside function bodies, type inference works for all const declarations.
Mutability
Section titled “Mutability”The mut keyword allows modification and ensures the value itself is mutable:
do main() {mut arr [i64] = {1, 2, 3}arr[0] = 10 // OKarr = {4, 5, 6} // OK}When assigning from a function return or other source, mut automatically makes the value mutable. There is no need to use copy() to obtain a mutable version:
import @arrays
do get_data() -> [i64] { return {1, 2, 3}}
do main() { mut arr = get_data() // arr is mutable arrays.append(arr, 4) // OK - can modify directly
const fixed [i64, 3] = {1, 2, 3} // fixed is immutable // arrays.append(fixed, 4) // ERROR - cannot modify const println(arr) println(fixed)}Variables and constants are block-scoped. A block is delimited by braces {}.
Inner scopes may declare variables that shadow outer scope variables:
// x is 10 here
do main() {mut x i64 = 10if true { mut x i64 = 20 // Shadows outer x // x is 20 here}}Return Value Handling
Section titled “Return Value Handling”All return values must be handled. If a function returns a value, you must either assign it to a variable or explicitly discard it with the blank identifier _. Silently ignoring a return value is not permitted.
Fallible Functions
Section titled “Fallible Functions”Some functions return a (T, Error) tuple; these are fallible functions. They require destructuring. Assigning the result to a single variable is a compile-time error (E3089); the compiler forces you to make the choice — inspect the error or explicitly discard it — visible in the code:
import @io
do main() { // Correct: handle the error mut content, err = io.read_file("data.txt") if err != nil { println(err) }
// Correct: explicitly discard the error when you know it won't fail mut other, _ = io.read_file("data.txt")
// Wrong: single-var assignment from a fallible function // mut third = io.read_file("data.txt") // error[E3089]: use destructuring for fallible functions println(content) println(other)}Blank Identifier
Section titled “Blank Identifier”The blank identifier _ discards a return value you don’t need:
import @json
do get_pair() -> (i64, i64) { return 1, 2 }do get_triple() -> (i64, i64, i64) { return 1, 2, 3 }
do main() { // Discard the second return value mut value, _ = get_pair()
// Discard multiple values const _, middle, _ = get_triple()
// Discard error intentionally mut text string = "1" mut data, _ = json.decode(text) println(value) println(middle)}The blank identifier:
- Cannot be read from (it discards the value)
- Can be used multiple times in the same assignment
- Works with both
mutandconstdeclarations - Makes it explicit that you are intentionally ignoring a value