Values & types
Declare variables, convert values, and represent missing data.
On this page
Valk checks types at compile time. You can let it infer local types from values while keeping function inputs and outputs explicit.
Declare and update a variable#
fn main() {
let quantity = 3
let price: float = 4.5
quantity += 2
println("Items: %quantity")
println("Total: %{quantity * price}")
}
quantity is inferred as int. price: float supplies an explicit type. A variable declared with let can be reassigned; its type stays fixed. Use %{expression} to insert an expression into a string.
Choose a number type#
| Type | Use |
|---|---|
int, uint |
Signed or unsigned integers sized for the compilation target |
i8, i16, i32, i64 |
Signed integers with an explicit width |
u8, u16, u32, u64 |
Unsigned integers with an explicit width |
float |
Floating-point numbers sized for the target |
f32, f64 |
Floating-point numbers with an explicit width |
bool |
true or false |
Use explicit widths for binary formats and native interfaces. Integer types expose their bounds through T.$min and T.$max, such as u8.$max for 255.
Convert and parse#
Use .to(Type) when a conversion should be explicit. Parsing text can fail, so decide how the program should handle invalid input:
fn main() {
let count = 12
let text = count.to(String)
let parsed = "42".to(int) !? 0
let fallback = "unknown".to(int) !? 0
println("%text, %parsed, %fallback")
}
The !? 0 supplies zero if parsing fails. Text outside the destination integer's range also produces a parsing error. For a user-facing input form, handle the error and explain what needs correcting instead of silently substituting a value.
Represent an optional value#
A ? before a type makes it nullable. Check it before using the underlying value, or provide a default with ??:
fn display_name(name: ?String) String {
if isset(name) {
return name
}
return "Guest"
}
fn main() {
let name: ?String = null
println(display_name(name))
println(name ?? "Anonymous")
}
isset narrows the value to its non-null type inside the branch. An early return works too: after if !isset(name) : return, the rest of the function can use name as a String.
Keep the two fallback operators distinct: ?? handles a null value; !? handles an error from a call.
Use the surrounding type#
When the destination already tells Valk the type, .{ ... } can omit a repeated type name:
let scores: Array[int] = .{ 10, 20, 30 }
This also works in typed function arguments and class properties. Spell out the type when it makes an example easier to understand.