Tipos
Os tipos primitivos, typeof, cast e as anotações opcionais verificadas.
Os tipos primitivos#
| Tipo | Exemplos | typeof devolve |
|---|---|---|
| Inteiro | 42, 0xFF, 0b1010, 1_000_000 | "Integer" |
| Decimal | 3.14, 1.5e3 | "Float" |
| Texto | "a", 'b', """várias linhas""" | "String" |
| Booleano | yes, no | "Boolean" |
| Nulo | void | "Void" |
| Lista | [1, 2, 3] | "Cluster" |
| Dicionário | {"k": 1} | "Vault" |
Os nomes Cluster e Vault valem uma explicação: são lista e dicionário, com nomes que descrevem o uso — um agrupamento de itens e um cofre de pares chave-valor.
typeof#
typeof x devolve o mesmo nome que você usaria numa anotação. Isso não é detalhe: significa que as duas formas falam a mesma língua.
idade: Integer := 30
out typeof(idade) # Integer
record Ponto:
x: Integer
y: Integer
enum Cor:
Vermelho
out typeof(42), typeof(3.14), typeof("a"), typeof(yes), typeof(void)
out typeof([1]), typeof({"k": 1})
out typeof(Ponto(1, 2)) # Ponto — o próprio nome do record
out typeof(Cor.Vermelho) # Cor — o nome do enumConversão#
cast valor as Tipo converte explicitamente:
out cast "42" as Integer # 42
out cast 3.9 as Integer # 3 — trunca, não arredonda
out cast 42 as String # "42"
out cast "3.5" as Float # 3.5
out str(42), int("7"), float("2.5"), bool(1)Uma conversão impossível dispara erro em vez de devolver lixo:
monitor:
cast "abc" as Integer
handle e:
out e.messageAnotações de tipo#
Opcionais, mas verificadas — tanto em tempo de execução quanto pelo analisador estático:
idade: Integer := 30
nome: String := "Ana"
notas: Cluster := [8, 9, 10]
config: Vault := {"tema": "escuro"}
# recusado:
# quantidade: Integer := 3.5Os nomes aceitos, com seus sinônimos:
| Canônico | Também aceita |
|---|---|
Integer | integer, int |
Float | float |
Number | number — aceita Integer ou Float |
String | string, str, text |
Boolean | boolean, bool |
Cluster | cluster, list, array |
Vault | vault, dict, map |
Void | void, none |
Action | action, function |
Any | any — desliga a checagem |
Qualquer outro nome é tratado como nome de record, enum ou blueprint, e a checagem percorre a cadeia de herança.
A regra de alargamento#
Há uma única flexibilização, e ela existe porque é matematicamente segura:
media: Float := 8 # ok: todo inteiro é um decimal válido
# quantidade: Integer := 3.5 # erro: 3.5 não é inteiroUm Integer entra onde se espera Float. O contrário perderia informação, e por isso é recusado.
Tipagem gradual com Any#
Any diz explicitamente "qualquer tipo serve". É diferente de não anotar:
| Forma | Significa |
|---|---|
action f(x): | não pensei sobre o tipo |
action f(x: Any): | pensei, e qualquer tipo serve |
A segunda comunica intenção. Aceitar Any não significa tratar tudo igual — o padrão é estreitar logo na entrada com pattern matching:
action descrever(v: Any) -> String:
match v:
point Integer as n:
yield $"inteiro {n}"
point String as s:
yield $"texto de {len(s)} letras"
point Cluster as c:
yield $"lista com {len(c)} itens"
default:
yield "outro"