Skip to content

Tipos

Soyuz tem um sistema de tipos estático com inferência. O compilador conhece o tipo de cada expressão em tempo de compilação, mas você raramente precisa anotar tudo.


TipoDescriçãoExemplos
IntInteiro 64-bit0, 42, -7
FloatPonto flutuante 64-bit3.14, -0.5, 1.0
BoolBooleanotrue, false
StringTexto UTF-8"olá", "mundo"
CharCaractere Unicode'a', 'ç'
UnitAusência de valor()
val inteiro: Int = 42
val decimal: Float = 3.14
val ativo: Bool = true
val texto: String = "Soyuz"
val vazio: Unit = ()

Strings são delimitadas por aspas duplas e suportam interpolação com $():

val nome = "Vand"
val saudacao = "Olá, $(nome)!" // "Olá, Vand!"
val calculo = "Resultado: $(1 + 2 * 3)" // "Resultado: 7"

Raw strings (sem processamento de escape) usam o prefixo r:

val regex = r"\d+\.\d+"
val caminho = r"C:\Users\vand\docs"

Tuplas agrupam valores de tipos diferentes. São imutáveis e têm tamanho fixo.

val par: (Int, String) = (1, "um")
val trio = (true, 3.14, "pi")
// Desestruturação
val (n, s) = par
val (flag, valor, label) = trio

Unit é essencialmente uma tupla vazia ().


Records são estruturas de dados imutáveis e sem comportamento. São o tipo ideal para DTOs, valores de domínio e dados puros.

record Ponto {
x: Float
y: Float
}
record Usuario {
id: Int
nome: String
email: String
}
val p = Ponto { x: 1.0, y: 2.0 }
val u = Usuario { id: 1, nome: "Vand", email: "vand@soyuz.dev" }
val distX = p.x // 1.0
val nome = u.nome // "Vand"

Records têm deep equality automática. Dois records são iguais se todos os seus campos são iguais:

val p1 = Ponto { x: 1.0, y: 2.0 }
val p2 = Ponto { x: 1.0, y: 2.0 }
p1 == p2 // true — compara por valor
record Par[A, B] {
primeiro: A
segundo: B
}
val coords = Par[Int, Int] { primeiro: 10, segundo: 20 }

Enums representam um valor que pode ser uma de várias variantes. Cada variante pode carregar dados.

enum Forma {
Circulo(raio: Float)
Retangulo(w: Float, h: Float)
Ponto
}
enum Direcao {
Norte
Sul
Leste
Oeste
}
val c = Forma.Circulo(raio: 5.0)
val r = Forma.Retangulo(w: 10.0, h: 4.0)
val d = Direcao.Norte
fn area(f: Forma) -> Float {
return match f {
Circulo(raio) => 3.14159 * raio * raio
Retangulo(w, h) => w * h
Ponto => 0.0
}
}
enum Arvore[T] {
Folha
No(valor: T, esq: Arvore[T], dir: Arvore[T])
}

Option[T] representa um valor que pode ou não existir. Tem duas variantes:

  • Some(T) — tem um valor
  • None — não tem valor
fn buscarPorId(id: Int) -> Option[Usuario] {
// retorna Some(usuario) ou None
}
val resultado = buscarPorId(42)
val nome = match resultado {
Some(u) => u.nome
None => "Usuário não encontrado"
}

O tipo T? é equivalente a Option[T]:

fn buscar(id: Int) -> Usuario? // mesmo que Option[Usuario]
val nome: String? = None
val email = buscar(1)?.email // String? — None se buscar retornar None
val display = buscar(1)?.nome ?: "Anônimo"

Result[T] — operações que podem falhar

Section titled “Result[T] — operações que podem falhar”

Result[T] representa o resultado de uma operação que pode falhar. Tem duas variantes:

  • Ok(T) — sucesso com valor
  • Err(E: Error) — falha com erro

O tipo do erro é sempre algo que implementa a interface Error (da biblioteca padrão).

fn dividir(a: Int, b: Int) -> Result[Float] {
if b == 0 {
return Err(DivisaoErro { motivo: "divisão por zero" })
}
return Ok(a.toFloat() / b.toFloat())
}
val resultado = dividir(10, 2)

Assim como em Option, o Result suporta auto-wrapping: Ok(v) pode ser apenas v e Err(e) pode ser apenas e (se e for um Error).

match resultado {
Ok(v) => print("Resultado: $(v)")
Err(e) => print("Erro: $(e.message())")
}

O operador |?> curto-circuita automaticamente quando uma etapa retorna Err ou None:

val dados: Result[Dados] = buscar(1) |?> validar |?> transformar
// Se qualquer etapa retornar Err ou None, o pipeline para e propaga o erro.

Qualquer tipo pode ser parametrizado com []:

List[Int]
Map[String, Float]
Option[Usuario]
Result[Dados]
Par[Int, String]

Primitivos Int, Float, Bool, String, Char, Unit
Compostos record (imutável, dados puros)
class (dados + comportamento)
enum (sum types / ADTs)
Coleções List[T], Map[K, V]
Especiais Option[T] / T? (presença opcional)
Result[T] (falha com motivo)
Estruturais (A, B, C) (tupla)
(A, B) -> C (tipo de função)