Enums
Conjuntos fechados de valores nomeados, com valores associados e integração com match.
Declarar#
enum Status:
Rascunho
Publicado
ArquivadoCada membro carrega três coisas:
out Status.Publicado.name # "Publicado" — o identificador
out Status.Publicado.value # "Publicado" — o valor (padrão: o nome)
out Status.Publicado.index # 1 — a posição na declaraçãoO problema que resolve#
Sem enum, estados viram texto solto:
pedido := {"status": "publicado"}
given pedido["status"] is "Publicado": # nunca entra: caixa diferenteUm erro de digitação vira um no silencioso. Com enum, Status.Publicad é erro na hora — e o `dataforge check` acha antes mesmo de rodar:
Enum 'Status' has no member 'Publicad'. Members: Rascunho, Publicado, ArquivadoValores associados#
enum Prioridade:
Baixa := 1
Media := 5
Alta := 10
Critica := 100
enum Moeda:
Real := "BRL"
Dolar := "USD"Sem :=, o valor é o próprio nome. Com :=, é o que você escrever.
A ponte com o mundo externo#
Dentro do programa você quer Moeda.Real. Mas o banco guarda "BRL", a API devolve "BRL", o CSV tem "BRL". O valor é a ponte:
vinda_do_banco := "BRL"
moeda := Moeda.from_value(vinda_do_banco) # Moeda.Real
moeda := Moeda.from_value(entrada) ?? Moeda.Real # com padrãofrom_value devolve void para um valor desconhecido, em vez de inventar um membro. Combinado com ??, isso vira um padrão limpo.
Valores numéricos como ordem#
tarefas := [
{"titulo": "revisar", "prio": Prioridade.Baixa},
{"titulo": "deploy", "prio": Prioridade.Critica}
]
out sorted(tarefas >> morph t: t["prio"].value) # [1, 100]Isso é mais expressivo que depender de .index: o índice reflete a ordem de declaração, o valor reflete a ordem de negócio. Inserir um membro no meio muda os índices, mas não os pesos.
Os utilitários#
| Chamada | Devolve |
|---|---|
Status.names() | ["Rascunho", "Publicado", "Arquivado"] |
Status.values() | os valores |
Status.members() | os membros, para percorrer |
Status.count() | 3 |
Status.has("X") | yes / no |
Status.from_name("X") | o membro, ou void |
Status.from_value(v) | o membro com aquele valor, ou void |
cycle s in Status.members():
out $" {s.index}: {s.name}"Com match#
action acao(luz):
match luz:
point Semaforo.Vermelho:
yield "frear"
point Semaforo.Amarelo:
yield "reduzir"
point Semaforo.Verde:
yield "acelerar"
default:
yield "estado desconhecido"Máquina de estados#
O padrão completo tem três partes: o enum enumera os estados, uma tabela declara as transições legítimas, e as ações só consultam a tabela.
enum Pedido:
Novo
Pago
Enviado
Entregue
steady TRANSICOES := {
"Novo": ["Pago"],
"Pago": ["Enviado"],
"Enviado": ["Entregue"],
"Entregue": []
}
action pode_ir(de, para):
yield para.name in TRANSICOES[de.name]
out pode_ir(Pedido.Novo, Pedido.Pago) # yes
out pode_ir(Pedido.Novo, Pedido.Entregue) # noNenhum estado inválido é representável, e nenhuma transição inválida é possível. Entregue com lista vazia é um estado terminal.