Pular para o conteúdo

Anotações de tipo

Tipos opcionais em variáveis, parâmetros e retorno — verificados em execução e por análise estática.

A forma#

dataforge
idade: Integer := 30                        # variável

action media(nums: Cluster) -> Float:        # parâmetro e retorno
    yield sum(nums) / len(nums)

lambda (n: Integer): n + 1                   # lambda (exige parênteses)

Anotar é opcional. O código funciona sem, mas quando presente a anotação é verificada — pelo interpretador e pelo `dataforge check`.

O que é verificado#

  • O valor atribuído a uma variável anotada
  • Cada argumento passado a um parâmetro anotado, na fronteira da ação
  • O valor devolvido pelo yield, contra o tipo declarado
  • Se uma ação com retorno declarado pode terminar sem yield (aviso)

Por que na fronteira#

Compare as duas formas de errar:

text
TypeError_: unsupported operand type(s) for *: 'str' and 'int'

parameter 'largura' of action 'area' declared as Number but got String

A segunda diz onde e o quê. É por isso que a checagem acontece na entrada da ação, e não lá dentro quando a conta explode.

Os nomes aceitos#

CanônicoSinônimosAceita
Integerinteger, intinteiros
Floatfloatdecimais e inteiros
Numbernumberinteiros ou decimais
Stringstring, str, texttextos
Booleanboolean, boolyes / no
Clustercluster, list, arraylistas
Vaultvault, dict, mapdicionários
Voidvoid, noneapenas void
Actionaction, functionações e lambdas
Streamstreamo retorno de um stream action
Anyanytudo — desliga a checagem

Qualquer outro nome é tratado como record, enum ou blueprint, e a checagem percorre a cadeia de herança.

A regra de alargamento#

dataforge
media: Float := 8              # ok — todo inteiro é um decimal válido
quantidade: Integer := 3.5     # erro — 3.5 não é inteiro

Um Integer entra onde se espera Float. O contrário perderia informação, e por isso é recusado. Essa é a única flexibilização do sistema.

Coleções: o recipiente, não o conteúdo#

dataforge
notas: Cluster := [7.5, 8.0]      # "é uma lista" — nada diz sobre os itens

DataForge 4.0 ainda não tem Cluster<Float>generics estão no roadmap. Enquanto isso, o conteúdo se valida com código:

dataforge
action todos_numeros(valores: Cluster) -> Boolean:
    cycle v in valores:
        given typeof(v) isnt "Integer" and typeof(v) isnt "Float":
            yield no
    yield yes

Records: campos sempre tipados#

Diferente de variáveis e parâmetros, o tipo de um campo de record é obrigatório:

dataforge
record Usuario:
    nome: String
    idade: Integer
    email: String := "sem@email"    # com valor padrão

A checagem estática#

O dataforge check encontra os mesmos problemas antes de executar, com sugestão de correção:

text
app.df:14:1: erro: Declared as String but the value is Integer
    sugestão: Change the annotation to Integer or fix the value
app.df:13:1: erro: Unknown type 'Intger'
    sugestão: Did you mean 'Integer'?

Detalhes em Análise estática.