Values and types
Goal: declare values, get to know the primitive types, and understand the two decisions that change day-to-day life the most: no
nulland no implicit zero-value.
Declaration: let / var / const, and the := shortcut
Section titled “Declaration: let / var / const, and the := shortcut”Immutable is the default; the common case carries no keyword:
x := 5 // immutable, runtime (shortcut, the common case)let y := 5 // immutable, runtime (explicit form; identical to 'x := 5')var z := 5 // mutableconst N := 64 // compile-time constant (comptime)
nome: string = "ana" // explicit type (Odin style); ':=' is ': =' with the type omittedThe rule: := (or : T =) declares; a bare = only assigns to a var. The : is what marks a
declaration.
z = 10 // ok: z is varx = 10 // ERROR: x is not varAnd a rule that gives teeth to immutable-by-default: a var that is never mutated is a compile error, and
the compiler tells you to use :=. A capability that is requested and not exercised does not pass.
Primitive types
Section titled “Primitive types”- Arbitrary-width integers:
iN/uNfor anyNfrom 1 to 65535.u8,i32,u7,i128,u777are all valid. Aliases:int/uint(default width),isize/usize(pointer width),byte=u8,bit=u1. - Floats only in IEEE widths:
f16/bf16/f32/f64/f128; aliasfloat. bool(true/false),string(always valid UTF-8).
conta: u64 = 0ratio: float = 0.5ativo: bool = trueflags: u3 = 0b101 // 3 real bits; takes up 1 addressable byteSize and duration literals
Section titled “Size and duration literals”The lexer understands units, with no import needed:
@limit(16mb) // 16 megabytes (base-10). '16mib' = base-2. the atom is the byte.prazo := 5s // Duration: 5 seconds. also 300ms, 10ns, 6m, 7h, 18dSizes become usize in bytes; durations become Duration. For runtime values there are helpers
(mem.mib(n), time.millis(n)).
No null: absence is Optional[T]
Section titled “No null: absence is Optional[T]”There is no null in Makoto. When something can be missing, the type says so with Optional[T], and the
empty case is the builtin value none:
fn buscar(id: int) -> Optional[User] { if id == 0 { return none } return achar(id) // a present User coerces into Optional[User]}
u := buscar(42)nome := u.is_present() ? u.or_panic().name : "anonymous"The access API is honest in its naming: is_present()/is_none(), or_panic() (returns the value;
panics if empty, and the name shows the consequence), or(default) (value or default). Or you
branch with match:
match buscar(42) { none => io.println("not found") user => io.println("found {{user.name}}")}No implicit zero-value
Section titled “No implicit zero-value”Every declaration is born with a right-hand side. There is no var x: int that turns into 0 on its own: 0 and "" only
show up when you write them. This eliminates the whole class of “I forgot to initialize” bugs:
there is nothing to forget.
var total := 0 // 0 because I wrote 0var nome := "" // "" same thingNext: 02 · Functions and flow