10 pontos por GN⁺ 2026-03-15 | 1 comentários | Compartilhar no WhatsApp
  • A Receita Federal dos EUA disponibilizou em código aberto o novo Tax Withholding Estimator (TWE), e o princípio central do projeto é uma estrutura que modela a legislação tributária dos EUA como uma especificação declarativa baseada em XML
  • A lógica de cálculo tributário do TWE é construída sobre um mecanismo chamado Fact Graph, que representa cada item tributário como um grafo de dependências de "fatos (Facts)" definidos em XML
  • Implementar a lógica tributária em uma linguagem imperativa como JavaScript causa problemas como gerenciamento da ordem de execução, perda de valores intermediários e exposição de detalhes de implementação, por isso a abordagem declarativa é essencial
  • JSON não é adequado para lidar com expressões aninhadas arbitrárias, e no XML a própria tag indica o tipo do objeto, o que o torna muito mais favorável para construir DSLs
  • O XML permite aproveitar gratuitamente um ecossistema maduro de ferramentas, como XPath, tornando-se a opção mais econômica para especificações declarativas multiplataforma

Fact Graph: a legislação tributária dos EUA expressa em XML

  • O Tax Withholding Estimator (TWE), divulgado pela IRS, é uma ferramenta que permite ao contribuinte informar renda e deduções para estimar impostos e retenções na fonte
    • O projeto foi publicado como código aberto e também aceita contribuições do público
  • O TWE é um site estático gerado a partir de duas configurações em XML, sendo a primeira um Fact Dictionary que representa a legislação tributária dos EUA
  • O Fact Graph é um mecanismo de lógica originalmente criado para o projeto IRS Direct File e calcula a obrigação tributária e a retenção do contribuinte com base nos fatos definidos no Fact Dictionary
  • Cada fato é definido em XML; por exemplo, /totalOwed é expresso como um fato derivado (Derived) que subtrai /totalPayments de /totalTax
    • O "valor total devido (total owed)" é a diferença entre o imposto total sobre a renda (total tax) e o valor já pago (total payments)
  • Créditos reembolsáveis (refundable credits) são créditos tributários que podem tornar o saldo de imposto negativo; Earned Income Credit, Child Tax Credit e American Opportunity Credit são somados com <Add>
  • Créditos não reembolsáveis (non-refundable credits) só podem reduzir a carga tributária até 0; com o operador <GreaterOf>, escolhe-se o maior valor entre 0 e (imposto provisório - créditos não reembolsáveis)
  • Os valores informados pelo usuário usam a tag <Writable> em vez de <Derived>, e o tipo do valor é especificado com <Dollar/>, <Boolean/> etc.
  • Os fatos dependem uns dos outros em uma estrutura de grafo que produz o valor final do imposto

Por que a lógica tributária precisa de especificações declarativas

  • Se o mesmo cálculo fosse escrito em JavaScript, const totalOwed = totalTax - totalPayments pareceria simples, mas isso é uma abordagem imperativa: a execução é sequencial e as etapas intermediárias se perdem
  • Quando as dependências se aprofundam, surgem problemas de ordem de execução: uma função de entrada do usuário como getInput() bloqueia todos os cálculos posteriores, e as próprias perguntas precisam mudar conforme a existência ou não de um cônjuge
  • Na lógica de soma da renda do Social Security, detalhes de implementação em JavaScript como map/reduce ficam expostos, enquanto <CollectionSum> em XML expressa o próprio conceito matemático tributário
    • <Dependency path="/socialSecuritySources/*/totalFederalTaxesPaid"/> soma os itens dentro da coleção
  • O Fact Dictionary segue uma abordagem declarativa: basta descrever os cálculos nomeados e suas dependências, sem detalhar etapas concretas nem ordem de execução, e o mecanismo decide automaticamente como executar
  • A vantagem mais importante do modelo tributário declarativo é a auditabilidade e a introspecção: é possível perguntar ao programa "como este número foi obtido?"
    • Em programas imperativos, os valores intermediários já foram descartados e só podem ser verificados com logs ou depuradores; isso não escala em um sistema como a legislação tributária dos EUA, com centenas de cálculos intermediários
  • Segundo Chris Given, autor original do Fact Graph, o Fact Graph é um meio de provar que itens não perguntados não alteraram o resultado da declaração e que todos os benefícios fiscais elegíveis foram considerados
  • A Intuit, criadora do TurboTax, chegou à mesma conclusão e publicou em 2020 um white paper sobre o "Tax Knowledge Graph", mas a implementação não é pública
    • Já o Fact Graph da IRS é código aberto e domínio público, podendo ser estudado, compartilhado e expandido por qualquer pessoa

Por que XML é muito mais adequado que JSON para DSLs

  • Ao tentar usar JSON como formato declarativo para expressar a legislação tributária, lidar com expressões aninhadas arbitrárias se torna muito desconfortável
    • Como a única estrutura de dados composta do JSON é o objeto, todo objeto filho precisa declarar seu tipo com algo como "type", "kind" etc.
    • No XML, o próprio nome da tag representa o tipo do objeto, então não é necessário declarar isso separadamente
  • A representação em JSON do mesmo fato /tentativeTaxNetNonRefundableCredits acaba sendo mais longa e complexa do que em XML
  • XML oferece suporte a comentários e a um tratamento razoável de espaços e quebras de linha, sem as limitações incômodas que costumam ser tratadas como normais no JSON
  • A combinação de atributos (attribute) e elementos filhos nomeados (named children) oferece, no design da linguagem, expressividade para escolher o que enfatizar
  • Também é possível definir tipos de dados próprios, como a distinção entre "dólar" e "inteiro"
  • Ao lidar com textos explicativos longos, o XML é muito mais confortável para leitura e edição manual do que JSON

A generalidade do XML e seu ecossistema de ferramentas

  • Sintaxes alternativas como S-expression, Prolog e KDL podem ser mais fáceis de ler que XML, mas ao usar XML você ganha de graça o parser e um ecossistema de ferramentas de uso geral
    • S-expression funciona bem em Lisp, termos de Prolog funcionam bem em Prolog, mas XML pode ser convertido para qualquer formato
  • Em Prolog, converter XML para um termo de Prolog pode ser feito com um único predicado
  • O texto também menciona a pergunta do usuário ok123456 no Hacker News — "por que não usar Prolog/Datalog?" —; isso é possível, mas o XML leva vantagem em generalidade
  • Sobre YAML, Chris Given afirma: "nunca tente expressar a lógica da legislação tributária dos EUA em YAML"
  • Exemplo prático com XPath: foi criado um script que, com um único comando de shell, faz busca fuzzy por caminhos de fatos e consulta imediatamente a definição do caminho selecionado
    • cat facts.xml | xpath -q -e '//Fact/@path' | grep -o '/[^"]*' | fzf para buscar fatos
    • Também foi adicionada a função de subir a cadeia de dependências para rastrear quais fatos dependem daquele fato
    • Com cerca de 60 linhas de bash, isso evoluiu para uma ferramenta de depuração usada quase diariamente
  • Outros membros da equipe também criaram suas próprias ferramentas rápidas de depuração, todas fazendo parse simples do XML e trabalhando em suas linguagens preferidas sem mexer na implementação Scala do Fact Graph
  • A principal lição: representações genéricas de dados têm enorme valor, e nessa categoria existem apenas JSON e XML
    • Na maioria dos casos deve-se escolher JSON, mas quando é preciso uma DSL, XML é a opção mais barata, e essa eficiência de custo permite que a equipe use o orçamento de inovação em outras áreas

Observações adicionais

  • Mesmo pessoas que não programam conseguem ler XML se o esquema estiver bem projetado, embora seja desejável construir visualizações alternativas em separado
  • O interesse por XML vem crescendo novamente: por exemplo, a ferramenta grex, de Jake Low, que converte documentos XML para uma representação plana orientada a linhas, e o Xee, de Martijn Faassen, um motor moderno de XPath/XSLT implementado em Rust
  • Como os fatos do TWE servem para estimar retenção na fonte, eles não devem ser usados diretamente para declaração de imposto

1 comentários

 
GN⁺ 2026-03-15
Comentários do Hacker News
  • XML é um formato caro de analisar corretamente em várias linguagens
    Na prática, para implementar algo próximo do padrão, é preciso depender de três implementações open source como libxml2, expat e Xerces
    O ponto central das linguagens da família SGML é tratar “listas” como objetos de primeira classe e aninhamento como objeto de segunda classe, além de permitir adicionar metadados em dois eixos: nomes de tags e atributos
    XML ainda é útil como DSL, mas se for usar XML de verdade, a palavra “cheap” precisa ser descartada
    Também é possível fazer uma DSL declarativa parecer uma expressão imperativa. Por exemplo, algo como totalOwed = totalTax - totalPayments pode ter o mesmo significado de uma DSL em XML
    Linguagens como METAFONT mostram essa abordagem (link de exemplo)

    • Vejo XML repetindo os mesmos erros com frequência
      Muita gente esquece a verdade simples de que quanto mais funcionalidades você coloca em um formato, mais difícil fica analisá-lo
      JSON é popular porque tem poucos recursos e por isso é fácil de analisar
      Já o XML colocou coisa demais: attributes, namespaces, CDATA, DTDs etc.
      Também já houve discussões sobre usar SQLite como formato de intercâmbio, mas isso também corre o risco de ficar complexo como XML
      É por isso também que CSV continua amado por ser simples
      As tentativas atuais de enfiar comentários ou informação de tipos em JSON são uma recriação dos piores atributos do XML

    • Concordo, como autor do texto
      Dá para fazer uma especificação declarativa parecer uma fórmula matemática, mas no fim isso significa criar uma nova linguagem
      Aí surge o problema de portar o parser para todos os ambientes
      Também é preciso decidir pessoalmente coisas sintáticas como precedência de operadores ou expressões switch, e a complexidade acaba explodindo
      Foi exatamente por isso que usei a palavra “cheap” — usar um formato que já tem parser e tooling em todos os ambientes reduz custos
      A expressividade diminui, mas para equipes pequenas é uma escolha sensata

    • Usei muito XML em Java enterprise, e ele era o principal culpado por gargalos de memória e CPU
      XML não é cheap de jeito nenhum

    • O núcleo do SGML é o modelo de conteúdo baseado em expressões regulares dos elementos
      Não é só uma estrutura de listas; ele também permite definir regras de produção gramaticais como em BNF

    • Dizer “XML proper” em vez de “XML lookalike” parece preciosismo demais
      Mesmo sem usar todos os recursos do XML, ele continua sendo XML
      É como chamar um ônibus escolar de “imitação de ônibus” só porque ele não tem porta-copos

  • Acho que basta usar uma linguagem com bom suporte a eDSL em vez de XML
    Linguagens como Haskell, OCaml e Scala permitem expressar computação paralela com facilidade por meio de conceitos como applicative e arrow
    Em JavaScript também dá para criar abstrações como sum em vez de .reduce()
    Se você criar uma DSL em XML, acaba tendo que resolver de novo problemas como paralelização, legibilidade e inventar uma nova sintaxe
    Em domínios complexos, há grande chance de esbarrar na décima lei de Greenspun

    • Mas linguagens como Haskell têm o problema de serem difíceis de aprender
      Até desenvolvedores com 30 anos de carreira sentem que a barreira de entrada é alta

    • Raku também é uma boa opção
      Começou com base em Haskell e oferece Grammar embutida e estilo funcional, o que favorece a escrita de DSLs

    • HTML! (resposta curta em tom de brincadeira)

    • Lisp também serve
      Basta olhar para S-expressions para perceber o quanto XML parece verboso e pesado

  • Dá para projetar melhor a estrutura do JSON
    Se cada nó for composto de uma chave de tipo e um valor em array, fica possível representá-lo como uma S-expression
    Isso permite parsing em streaming e possibilita saber o tipo primeiro
    É útil em datasets grandes

    • JSON é muito mais simples que XML e tem custo de parsing menor
      No XML, casar tags e tratar atributos exige gerenciamento de estado mais complexo
      No JSON, basta casar {} e []
      Essa simplicidade vai se acumulando e resulta em menor latência

    • Mas JSON tem aspas demais, a ponto de parecer ruído visual
      Pessoalmente, acho o EDN do Clojure mais limpo

    • Esse tipo de estrutura em JSON parece, esteticamente, uma forma degenerada
      Se os dados precisam de tags, talvez seja melhor usar uma forma de representação adequada a isso

  • O texto The Lost Art of XML me pareceu mais interessante
    Achei marcante a visão de que boa parte das ferramentas de desenvolvimento web surgiu como consequência da derrota do XML nas browser wars

    • Mas acho difícil concordar com a afirmação de que “XML foi abandonado porque JavaScript venceu”
      Os navegadores originalmente também suportavam XML (o X de AJAX é XML)
      Os desenvolvedores é que simplesmente não gostavam de XML
      Acho que ele foi rejeitado por causa de excesso de engenharia e complexidade

    • Tendo vivido diretamente a era das APIs em XML, XML era realmente doloroso
      Era preciso criar encoder/decoder separado em cada linguagem, e a manutenção também era difícil
      JSON mapeia simplesmente para arrays e objetos, então tem excelente compatibilidade entre linguagens
      Quando lembro do tempo desperdiçado em reuniões de design de XML Schema, JSON simplificou o design de APIs como o Prettier acabou com a discussão de tabs vs spaces

    • No fim, tudo começa com a atitude de “não quero aprender algo complexo”, mas com o tempo os recursos voltam a fazer falta

  • A autoridade fiscal da Polônia ama XML
    Mas o XML deles é tão obscuro que humanos não conseguem ler
    Nomes de campos são coisas como P_19N, e é preciso olhar o schema para entender o significado real
    Há até número de artigo de lei embutido
    Ironicamente, o redator da lei do VAT hoje trabalha com consultoria tributária

  • Eu uso pessoalmente uma DSL baseada em S-expressions
    Ela faz o papel de HTML e CSS em um runtime de navegador desktop baseado em WebAssembly,
    e também foi reutilizada numa linguagem de marcação própria para resolver problemas de sincronização de documentos
    Dá para ver exemplos relacionados no código de exemplo do CanvasUI, no arquivo de estilos e na ferramenta de documentação

    • S-expressions têm implementação de parser extremamente simples, a ponto de eu já ter usado isso em entrevistas
      Era marcante ver a reação dos candidatos no momento em que conseguiam implementar uma linguagem simples por conta própria
  • XML é menos uma DSL e mais uma ferramenta geral de parser/lexer
    Ele apenas transforma texto em AST; a DSL real é a especificação definida em cima disso
    Tem muitos recursos e é complexo, mas a vantagem é um ecossistema rico de tooling
    É mais adequado para processar texto gerado do que para escrita manual

  • Como a validação de schema XSD já vem embutida, é possível verificar imediatamente a consistência do documento
    Reclamar que XML é difícil sem usar ferramentas de automação é como lidar com binários sem disassembler

    • Mas a validação por schema, sozinha, não garante a correção do conteúdo
      É o mesmo princípio de type checking não garantir a correção de um programa

    • XSD é útil, mas complexo e cheio de limitações
      Por isso parte da comunidade XML migrou para RELAX-NG, embora ele não tenha conseguido substituí-lo completamente

    • Fico curioso sobre que tipo de trabalho realmente exige validação com XSD

  • XML é aceitável como linguagem de marcação e serve razoavelmente como formato de troca de dados, mas é terrível como linguagem de programação
    JSON é parecido nesse ponto: é bom para intercâmbio de dados, mas se você tentar usá-lo como linguagem vai se arrepender
    Linguagens baseadas em YAML, como Ansible, são exemplo disso
    Já as S-expressions do Lisp têm estrutura parecida com a do JSON e mesmo assim evoluíram para uma linguagem excelente

  • O problema do XML não é tanto o XML em si, mas a dificuldade de gerar um XML bom
    O padrão é complexo, e cada produtor representa as coisas de um jeito diferente, o que reduz a consistência
    No JSON, essa variação é muito menor
    Ver XML de instituições financeiras chega a dar desespero

    • O problema do XML, no fim, vinha da lentidão do tooling e de validadores incompletos
      Mais do que a complexidade da representação dos dados, a qualidade das ferramentas era o verdadeiro gargalo

    • Na verdade, o problema não era “XML bom”, e sim que era fácil demais produzir XML horroroso
      Por isso a comunidade tentou garantir interoperabilidade com namespaces, validação, transformação, web semântica etc.
      Era um compromisso para conseguir tocar o trabalho adiante em ambientes onde consenso perfeito era impossível