Pular para o conteúdo

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#

dataforge
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#

MomentoO que acontece
dataforge check, com o literal na mãoacusa, e lista os valores que valem (tipo-literal)
dataforge check, com uma variávelcala — não há o que provar
execução, em toda fronteirarecusa, nomeando o tipo e o que chegou
dataforge
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#

dataforge
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 quandoUse 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 nadavocê quer método, .name, .value e exaustividade no match
a lista é pequena e fechadaa lista cresce, ou carrega comportamento