Appendix A: Odin quick reference
A one-page reminder of the Odin features this book uses. For the whole language, see *Understanding the Odin Programming Language* and the official overview.
Declarations
NAME :: value // compile-time constant (also procs and types)
x := value // variable, type inferred
y: f32 = value // variable, explicit type
Procedures
add :: proc(a, b: int) -> int { return a + b }
pair :: proc() -> (a: int, ok: bool) { return 42, true } // multiple returns
f :: proc(protected := false) {} // default argument
Primitive types
bool; i8 i16 i32 i64, u8 u16 u32 u64; int uint (pointer-sized); f32 f64; rune, string, cstring, rawptr. No implicit conversion; convert explicitly: f32(n), int(x). C interop types come from core:c: c.int, c.uint.
Untyped-constant gotcha: a float constant assigned with
:=defaults tof64. Pin the type when mixing withf32:air: f32 = 2 * A / B.
Structs and enums
Player :: struct { pos: Vec2, on_ground: bool } // every field has a zero value
p := Player{pos = {0, 400}} // unset fields are zero
Kind :: enum u8 { Rock, Boulder, Stump } // Rock = 0, ...
Defs := [Kind]int { .Rock = 1, .Boulder = 2, .Stump = 3 } // enumerated array (must be complete)
distinct T makes a fresh type with T's representation (raylib: Color :: distinct [4]u8).
Arrays
fixed: [64]Obstacle // fixed-size, inline, no allocation
slice: []u8 // (ptr, len) view; buf[:] makes one
dynamic: [dynamic]int // growable, allocates
Array programming on [N]f32: a + b, a * 2 (broadcast), a * b (component-wise), a.x, a.yx (swizzle). Vec2 :: rl.Vector2 is [2]f32.
Pointers
p := &x // address-of
p^ // dereference
for &o in xs { o.field = 1 } // &o mutates the element in place; without &, you edit a copy
Control flow
if cond { } else { }
if !ok do return // single-statement form
switch v { case .A: ; case .B: } // no fallthrough; enum switches checked for completeness
switch { case x > 0: ; case: } // no-operand switch = if/else-if ladder
for i in 0 ..< n { } // half-open range (excludes n)
for i in 0 ..= n { } // closed range (includes n)
for cond { } // while-loop
for { } // infinite
defer stmt // run stmt at scope exit (reverse order)
Builtins (no import): min max clamp abs len.
context and calling conventions
context.random_generator = rand.default_random_generator(&state) // set for this scope
context.allocator = ...
f :: proc "c" (n: c.uint) { // C calling convention (e.g. a raylib callback)
context = runtime.default_context() // re-establish a context at the boundary
}
C interop essentials
cstring: zero-terminated. Literals convert for free; dynamic text viafmt.ctprintf(temp allocator, per-frame, no leak). Never keep a tempcstringpast the frame.- Shared value types with raylib:
Vector2([2]f32),Rectangle(struct),Color(distinct [4]u8). rawptr(raw_data(slice))to pass a slice's memory to a C API;([^]i16)(ptr)to view a raw pointer as a multi-pointer.
Standard library used
core:math (sin cos exp floor, PI TAU) · core:math/rand (create_u64, default_random_generator, float32, float32_range, int_max) · core:strconv (parse_int, write_int) · core:os (read_entire_file_from_path, write_entire_file) · core:fmt (ctprintf, println) · core:c (c.int, c.uint) · base:runtime (default_context).