Coleções e strings
Objetivo: usar
List/Map/Sete a camada funcional, e entender as regras de string (unidades explícitas, interpolação, comparação por byte).
List, Map, Set (pacote collections, tier 0)
Seção intitulada “List, Map, Set (pacote collections, tier 0)”Não são builtin: você as importa. List[T] é um array contíguo que cresce (não linked list):
use collections
var xs := List[int].new()xs.push(1); xs.push(2); xs.push(3)io.println("{{xs.len()}} itens")
primeiro := xs.get(0) // Optional[int] (acesso seguro; none fora dos limites)@requires(i < xs.len())fn at_seguro(xs: List[int], i: usize) -> int { return xs.at(i) } // 'at' contratadoAcesso é por método (xs.at(i)/xs.get(i)), não xs[i]: [i] cru é só para []T/[N]T/[*]T
builtin. get -> Optional (“talvez”), at -> T (“eu garanto”, sob contrato).
Map[K, V] é uma tabela hash; a chave precisa ser hashável, propriedade derivada por reflexão
(structs servem sem declarar nada):
m := Map[string, int].new()m.put("ana", 90)score := m.get("ana") // Optional[int]m.update_or_insert("ana", fn(cur) => cur.or(0) + 1) // entry API anti-duplo-lookupSet[T] é um conjunto hash (add/contains/union/intersection). Estruturas especializadas
(Deque, PriorityQueue, SortedMap, Trie, RingBuffer) ficam na lib oficial containers
(tier 1), no capítulo 12.
Camada funcional
Seção intitulada “Camada funcional”map/filter/fold/collect via UFCS; collect materializa no container que você escolhe:
pares := xs.filter(fn(x) => x % 2 == 0)dobr := xs.map(fn(x) => x * 2)soma := xs.fold(0, fn(acc, x) => acc + x)
como_set: Set[int] = primos.collect() // mesmo iterator, container de saída escolhido pelo tipoStrings
Seção intitulada “Strings”string é sempre UTF-8 válido. Tem três visões (.bytes, .codepoints, .chars, esta última de
grapheme), e s[i] é proibido (a unidade é ambígua). Você qualifica:
s := "café"b := s.bytes.len // nº de bytes (campo .len da view)n := s.chars.len // nº de graphemesc0 := s.char_at(0) // um graphemeview := s.chars[1..3] // '..' = view O(1); ':' = cópia O(n)A interpolação usa {{ }}, via a interface Display (interpolar tipo sem Display é erro de
compilação, sem nada de <Object@0x...>):
io.println("{{nome}} fez {{count}} pedidos, total {{total.fixed(2)}}")A comparação é byte-a-byte: ==/!= (igualdade de bytes), </> (ordem lexicográfica, que alimenta
um sort direto). A semântica Unicode (normalização, collation) é método, não operador, e não há
===:
a == b // bytes (o comum, rápido)a.equals(b, .semantic) // normalização Unicode (puxa tabelas de 'unicode', opt-in)Crescer uma string segue a regra de mutabilidade de sempre: var muta, por doubling, sem
StringBuilder separado (use string.with_capacity(n) quando souber o tamanho):
var buf := string.with_capacity(256)buf.append("a"); buf.append("b")Construir a partir de bytes: string.from[u8](bytes) -> Result[string, error{InvalidUtf8}] (valida
na borda).
Próximo: 06 · Processos e channels