Pular para o conteúdo

Tipos: o que é conferido, e quando

Anotar é opcional, e o que muda quando você anota. União, refinamento, opaco, genéricos — e onde o analisador cala de propósito.

A dúvida mais comum sobre tipos aqui não é como escrever — é quem confere, e quando. Há duas metades, e elas respondem em momentos diferentes: o dataforge check responde antes de rodar, o interpretador responde na fronteira. Saber qual está falando economiza muito tempo.

Anotar é opcional; conferir não é#

dataforge
// sem anotacao: roda, e o check cala sobre o tipo
x := 10

// com anotacao: o check prova o que der para provar, e a execucao
// confere na fronteira
idade: Integer := 30

action dobro(n: Integer) -> Integer:
    yield n * 2

assert dobro(idade) is 60
out "o tipo declarado vale na entrada e na saida"

`type`: uma declaração, seis formas#

O que muda é o que vem depois do :=.

dataforge
type Id := Integer                              // alias
type Numero := Integer | Float                  // uniao
type Positivo := Integer where valor bigger 0   // refinamento

action guardar(p: Positivo) -> Integer:
    yield p

assert guardar(7) is 7
out "o refinamento vale em TODA fronteira, nao so na criacao"

`<T>` solto não é conferido; `<T extends X>` é#

dataforge
// sem limite: documenta a relacao, e aceita qualquer valor
action eco<T>(x: T) -> T:
    yield x

// com limite: cobrado nas duas metades — o check na chamada, a
// execucao no valor. E dentro do corpo, um 'T extends Number' E um
// Number para o analisador: e o que deixa escrever 'a bigger b'.
action maior<T extends Number>(a: T, b: T) -> T:
    yield a given a bigger b otherwise b

assert eco("oi") is "oi"
assert maior(3, 9) is 9
out "o limite atravessa o adopt tambem"

O que o `check` prova a partir de um literal#

AcusaCódigo
xs[10] num cluster de trêsindice-fora-do-alcance
v["cidad"] num vault sem a chave, com sugestãochave-ausente
cycle i from 5 to 1 — nunca roda; step 0 — nunca terminacycle-vazio
1 is "1" — sempre noigualdade-impossivel
p.clientte num record, com sugestãomembro inexistente
P.criar(1, 2, 3) vindo de outro arquivoaridade entre módulos

E o que ele cala, de propósito#

O silêncio é tão projetado quanto o alarme. Um falso alarme ensina a ignorar mensagens — e depois a desligar a verificação inteira.

  • `v["k"] ?? padrao` não é acusado. O ?? é exatamente o que a dica daquele erro recomenda: um analisador que acusa o conserto que ele próprio sugere é um analisador que se desliga.
  • Um parâmetro de tipo não é um tipo. Sem isso, a trilha ganhava dois alarmes no capítulo que ensina genéricos.
  • O tipo declarado de uma ação decorada não vale. Não há como saber qual decorador substitui, e diante de duas respostas ele cala.
  • `xs[-1]` continua livre — tratar todo negativo como fora do alcance acusaria a forma normal de pegar o último item.

Silenciar uma regra, de propósito#

dataforge
cores := ["azul", "verde"]

// A regra tem de ser NOMEADA: um 'permitir' solto esconderia o erro
// seguinte, que ninguem pediu para esconder.
match cores:
    point c:                        // df: permitir point-inalcancavel
        out $"casou com {len(c)} cores"

out "a regra vale na linha, ou na de cima"