Tipos literais
Um valor vira um tipo: type Estado := "ativo" | "inativo". A conferência acontece onde o dado entra, e não espalhada por cinquenta comparações.
Um tipo literal é um tipo cujo conjunto de valores tem um elemento. Sozinho ele é curioso; em união ele é o recurso: type Estado := "ativo" | "inativo" diz, num lugar só, o que antes vivia espalhado em given e is "ativo" or e is "inativo" — e esquecido numa das fronteiras.
A forma#
type Estado := "ativo" | "inativo" | "suspenso"
type Nivel := 1 | 2 | 3
type Ligado := yes
action mudar(e: Estado) -> String:
yield e
assert mudar("ativo") is "ativo"
assert mudar("suspenso") is "suspenso"
out "a fronteira confere, e o resto do programa nao precisa"Texto, inteiro, decimal e booleano podem ser literais. void fica de fora de propósito: Void já é o tipo dele, e type T := void seria uma segunda forma de dizer a mesma coisa.
Onde ele é cobrado#
| Momento | O que acontece |
|---|---|
dataforge check, com o literal na mão | acusa, e lista os valores que valem (tipo-literal) |
dataforge check, com uma variável | cala — não há o que provar |
| execução, em toda fronteira | recusa, nomeando o tipo e o que chegou |
type Estado := "ativo" | "inativo"
// Provado antes de rodar: o literal esta na mao.
// e: Estado := "zzz"
// erro: a variável 'e' declared as Estado ("ativo" | "inativo")
// but the value is 'zzz'
// E cobrado na fronteira, quando o valor vem de fora.
action mudar(e: Estado) -> String:
yield e
recusou := no
monitor:
mudar("zzz")
handle Error as erro:
recusou := yes
assert recusou
out "o que o analisador nao prova, a fronteira cobra"`yes` e `1` não se confundem#
A comparação é por igualdade e por tipo. Em Python True == 1 é verdadeiro, e sem a conferência de tipo um type Ligado := yes aceitaria o número 1 calado — um valor que nunca foi escrito passando por um tipo que existe para não deixar.
A base de uma união de literais é conhecida#
type Estado := "ativo" | "inativo"
action rotulo(e: Estado) -> String:
// 'e' e um String para o analisador, e por isso isto e aceito:
// sem essa leitura, devolver 'e' num '-> String' seria acusado.
yield e + "!"
assert rotulo("ativo") is "ativo!"
out "uniao so de literais do mesmo tipo abre para a base"Uma união mista — "auto" | Integer — não tem base única, e ali o analisador volta a calar em vez de escolher uma: escolher faria ele aprovar o que a execução recusa.
Quando usar, e quando não#
| Use um tipo literal quando | Use um enum quando |
|---|---|
o valor é o dado — vem de um JSON, de uma coluna, de um ?estado= | o valor é um conceito do domínio, com nome próprio |
| você quer conferir na fronteira sem converter nada | você quer método, .name, .value e exaustividade no match |
| a lista é pequena e fechada | a lista cresce, ou carrega comportamento |