Genéricos
Genéricos permitem escrever código que funciona para múltiplos tipos sem perder as garantias do type checker. Em Soyuz, a sintaxe usa colchetes [].
Funções genéricas
Section titled “Funções genéricas”fn identidade[T](x: T) -> T { return x}
fn primeiro[T](lista: List[T]) -> Option[T] { return lista.first()}
fn trocar[A, B](par: (A, B)) -> (B, A) { val (a, b) = par return (b, a)}O compilador infere os tipos na chamada — você raramente precisa ser explícito:
val x = identidade(42) // T = Int, inferidoval y = identidade("oi") // T = String, inferidoval z = identidade[Bool](true) // explícito quando necessárioRecords genéricos
Section titled “Records genéricos”record Par[A, B] { primeiro: A segundo: B}
val coords = Par[Int, Int] { primeiro: 10, segundo: 20 }val info = Par { primeiro: "nome", segundo: 42 } // inferênciaClasses genéricas
Section titled “Classes genéricas”class Repositorio[T] { var items: List[T] = []
fn adicionar(self, item: T) { self.items.add(item) }
fn buscar(self, predicado: (T) -> Bool) -> Option[T] { return self.items.find(predicado) }}
val userRepo = Repositorio[Usuario] { items: [] }Interfaces genéricas
Section titled “Interfaces genéricas”interface Comparavel[T] { fn comparar(self, outro: T) -> Int // -1, 0, 1}
interface Iteravel[T] { fn proximo(self) -> Option[T]}Constraints
Section titled “Constraints”Constraints limitam quais tipos podem ser usados como parâmetro. A sintaxe é T : Interface:
fn ordenar[T : Comparavel[T]](lista: List[T]) -> List[T] { // pode usar T.comparar porque T implementa Comparavel return lista.sort(fn(a: T, b: T) => a.comparar(b))}Múltiplas constraints com +
Section titled “Múltiplas constraints com +”fn processar[T : Persistivel + Serializavel](item: T) -> Result[String] { val json = item.toJson() item.salvar() return json // auto-wrap Ok()}Constraints em classes
Section titled “Constraints em classes”class Cache[T : Serializavel] { var dados: Map[String, String] = [:]
fn armazenar(self, chave: String, valor: T) { self.dados[chave] = valor.toJson() }}Monomorphization
Section titled “Monomorphization”Soyuz usa monomorphization — para cada uso concreto de um genérico, o compilador gera código especializado. Isso significa:
- Zero custo de abstração — sem boxing, sem despacho dinâmico.
- Binários otimizados para cada tipo.
- Erros de tipo em tempo de compilação, não em runtime.
// O compilador gera versões especializadas:val a = identidade(42) // versão para Intval b = identidade("oi") // versão para StringEnums genéricos
Section titled “Enums genéricos”enum Arvore[T] { Folha No(valor: T, esq: Arvore[T], dir: Arvore[T])}
fn profundidade[T](arvore: Arvore[T]) -> Int { return match arvore { Folha => 0 No(_, e, d) => 1 + max(profundidade(e), profundidade(d)) }}