Pular para o conteúdo

O livro · 01

Valores e tipos

book.md · 96 linhas · 2 min de leitura

Objetivo: declarar valores, conhecer os tipos primitivos, e entender as duas decisões que mais mudam o dia a dia: sem null e sem zero-value implícito.

Imutável é o default; o caso comum não leva keyword:

x := 5 // imutável, runtime (atalho, o caso comum)
let y := 5 // imutável, runtime (forma explícita; idêntica a 'x := 5')
var z := 5 // mutável
const N := 64 // constante de compilação (comptime)
nome: string = "ana" // tipo explícito (estilo Odin); ':=' é ': =' com o tipo omitido

A regra: := (ou : T =) declara; = pelado só atribui a um var. O : é o que marca declaração.

z = 10 // ok: z é var
x = 10 // ERRO: x não é var

E uma regra que dá dente ao imutável-by-default: um var que nunca é mutado é erro de compilação, e o compilador manda você usar :=. Capacidade pedida e não exercida não passa.

  • Inteiros de largura arbitrária: iN/uN para qualquer N de 1 a 65535. u8, i32, u7, i128, u777 são todos válidos. Apelidos: int/uint (largura default), isize/usize (largura de ponteiro), byte = u8, bit = u1.
  • Floats só nas larguras IEEE: f16/bf16/f32/f64/f128; apelido float.
  • bool (true/false), string (sempre UTF-8 válido).
conta: u64 = 0
ratio: float = 0.5
ativo: bool = true
flags: u3 = 0b101 // 3 bits de verdade; ocupa 1 byte endereçável

O lexer entende unidades, sem importar nada:

@limit(16mb) // 16 megabytes (base-10). '16mib' = base-2. átomo é o byte.
prazo := 5s // Duration: 5 segundos. também 300ms, 10ns, 6m, 7h, 18d

Tamanhos viram usize em bytes; durações viram Duration. Para valores de runtime há helpers (mem.mib(n), time.millis(n)).

Não existe null em Makoto. Quando algo pode faltar, o tipo diz isso com Optional[T], e o vazio é o valor builtin none:

fn buscar(id: int) -> Optional[User] {
if id == 0 { return none }
return achar(id) // um User presente coage para Optional[User]
}
u := buscar(42)
nome := u.is_present() ? u.or_panic().name : "anônimo"

A API de acesso é honesta no nome: is_present()/is_none(), or_panic() (devolve o valor; panica se vazio, e o nome mostra a consequência), or(default) (valor ou default). Ou você ramifica com match:

match buscar(42) {
none => io.println("não achei")
user => io.println("achei {{user.name}}")
}

Toda declaração nasce com um lado direito. Não há var x: int que vira 0 sozinho: 0 e "" só aparecem quando você escreve. Isso elimina a classe inteira de bugs de “esqueci de inicializar”: não há o que esquecer.

var total := 0 // 0 porque eu escrevi 0
var nome := "" // "" idem

Próximo: 02 · Funções e fluxo