18 pontos por GN⁺ 2025-04-22 | 11 comentários | Compartilhar no WhatsApp
  • Pipelining é um recurso importante nas linguagens de programação para aumentar a legibilidade e a manutenibilidade do código
  • É uma forma que permite expressar o fluxo de dados de maneira natural, da esquerda para a direita e de cima para baixo
  • Em linguagens como Rust, o pipelining deixa o fluxo do código mais claro e aumenta a produtividade com os recursos de autocompletar da IDE
  • É aplicado em várias linguagens, como Haskell, Elm e SQL, e builder pattern e method chaining também podem ser considerados uma forma de pipelining
  • Tem impacto positivo em legibilidade, facilidade de edição, suporte da IDE e até em ferramentas de controle de versão (diff, blame)
  • Permite escrever código mais conciso e claro do que o estilo com funções aninhadas, sendo vantajoso também para colaboração e manutenção

Minha sintaxe de programação favorita: pipelining

O que é pipelining?

  • É um recurso que permite omitir um dos argumentos na lista de parâmetros ao passar o valor anterior adiante
  • Aumenta a legibilidade do código e facilita a adição de comentários
  • É um estilo de sintaxe centrado em dados, no qual operações de processamento contínuas são aplicadas em sequência
  • É muito usado em código de estilo funcional na forma de method chaining, como .map().filter().collect()
  • Em Rust, um exemplo representativo é o código a seguir:
    data.iter()  
        .filter(|w| w.alive)  
        .map(|w| w.id)  
        .collect()  
    
  • Em contraste, se todas as funções forem aninhadas, a estrutura fica assim, e é preciso ler de dentro para fora:
    collect(map(filter(iter(data), |w| w.alive), |w| w.id))  
    

Por que o pipelining é bom?

  • 1. Legibilidade e manutenibilidade

    • É fácil de ler de cima para baixo → o fluxo de dados acompanha a ordem em que as pessoas leem
    • É fácil adicionar comentários em cada linha
    • Mesmo em linhas longas, fica conciso e claro sem aninhamento de parênteses
  • 2. Facilidade de edição

    • Dá para adicionar facilmente uma nova função como .map() no meio, em uma única linha
    • Até em git diff e git blame, o rastreamento das mudanças aparece de forma mais limpa
  • 3. Suporte de IDE / LSP

    • Combina bem com uma estrutura em que a lista de autocompletar aparece ao pressionar a tecla .
    • É favorável à análise estática, que exige conhecimento claro dos tipos
    • Para esse recurso funcionar direito, a linguagem precisa ser baseada em tipagem estática (e.g. Rust, TypeScript)

Pipelining também no SQL?

  • Existe a proposta de transformar consultas SQL com SELECT aninhado em um estilo de pipeline
  • Exemplo:
    FROM customer  
    |> LEFT OUTER JOIN orders ON ...  
    |> AGGREGATE COUNT(...) GROUP BY ...  
    |> ORDER BY ...  
    
  • Em comparação com o SQL tradicional, oferece fluxo mais claro e melhor legibilidade
  • Desvantagem: como a cláusula SELECT sobe para o topo, pode ficar mais difícil entender o tipo de retorno → isso pode ser resolvido

Relação com o builder pattern

  • Formas como Builder::new().option().option().build() em Rust são uma estrutura típica de pipeline
  • Ao compor configurações opcionais como métodos, fica mais fácil rastrear o código e gerenciar alterações

Melhorias no pipelining em Haskell

  • Operadores como $, &, |> em Haskell permitem usar pipeline em vez de composição de funções
  • Comparação antes e depois do exemplo:
    -- 기존  
    checkPalindromes content = unlines $ map (show . isPalindrome) $ lines $ map toLower content  
    
    -- 개선  
    checkPalindromes content =  
      content  
        & map toLower  
        & lines  
        & map (show . isPalindrome)  
        & unlines  
    

Vantagens do pipelining em Rust

  • Method chaining, inferência de tipos e extensibilidade estrutural baseada em traits se combinam muito bem com pipelining
  • Rust tem uma estrutura que parece reunir apenas as vantagens da sintaxe funcional e orientada a objetos, tornando o uso de pipelining o mais natural possível

Conclusão

  • Pipelining não é apenas uma sintaxe, mas um recurso central que afeta fluxo de código, editabilidade e até colaboração
  • Em vez de aninhamentos como f(g(h(x))), a estrutura x |> h |> g |> f é mais amigável para humanos
  • Sob a regra simples de “uma operação por linha”, o pipelining é a melhor forma de expressar um fluxo natural

“Cada pedaço do pipeline recebe os dados principais e executa uma única tarefa. No final, se você der um nome claro ao resultado, essa será a estrutura de código ideal.”

11 comentários

 
progdesigner 2025-04-23

Acho que é mais ou menos o mesmo contexto em que, em qualquer texto,
quebras de linha e indentação são importantes para a legibilidade.

 
forgotdonkey456 2025-04-23

LINQ é o melhor!

 
bus710 2025-04-23

O Gleam também oferece suporte a isso, então dá para escrever código de forma bem limpa.

Aliás, não sei se é porque o texto principal tem um bloco de código, mas ele está aparecendo com layout de desktop até no celular.

 
bus710 2025-04-23

Pensando bem, elm também permite isso.

 
galadbran 2025-04-22

Com uma pequena quantidade de dados e um código simples como no exemplo acima, acho que fica bonito e não há nada de ruim nisso.

Mas, à medida que vai entrando um pouco de código dentro de map(), ... há uma tendência de o código ir ficando cada vez mais inchado, e, embora isso dependa da linguagem e da biblioteca de implementação, quando o volume de dados aumenta, em comparação com simplesmente acumular ou manipular os dados em uma estrutura de dados durante o processamento, pode facilmente ficar milhares de vezes mais lento.

E surgiu mais um motivo novo para eu deixar de preferir isso: vi esta matéria no celular, e a largura de nível de PC foi mantida do jeito que estava, fazendo o tamanho da letra ficar minúsculo demais, então ficou muito difícil ler a matéria T.T

Basicamente não prefiro isso e não faço esforço para escrever deliberadamente desse jeito.

 
bichi 2025-04-22

Por favor, coloquem isso também no js |> implorando humildemente

 
secret3056 2025-04-22

|> é lindo demais

 
howudoin 2025-04-22

É a sintaxe que eu mais odeio
Se o stack trace já estiver só um pouco enrolado, depurar vira um pesadelo

 
cosine20 2025-04-25

Concordo pra caramba

 
GN⁺ 2025-04-22
Comentários do Hacker News
  • O autor chama isso de "pipelining", mas acho que o termo correto é "method chaining"

    • Comparando com um pipeline simples do Bash: cada componente é executado em paralelo e os resultados intermediários são transmitidos em streaming
    • Em Ruby, cada linha é processada sequencialmente e um array completo é criado entre cada etapa
    • Isso dificulta a depuração, então hoje em dia escrevo código mais explícito
    • Código explícito parece menos elegante, mas facilita inspecionar estados intermediários
  • Pessoalmente, apoio manter pequeno o conjunto de funcionalidades de uma linguagem e chegar rapidamente a um conjunto de funcionalidades completo

    • Mas gostaria que todas as linguagens adotassem a sintaxe |> do Elixir
  • As macros de Lisp oferecem uma solução geral que permite determinar a ordem da cadeia de chamadas, não apenas encadear operadores de coleção

    • Por exemplo, é possível escrever (foo (bar (baz x))) como (-> x baz bar foo)
    • Também consegue lidar com casos em que há argumentos adicionais
    • Para mais detalhes, veja o guia de macros de threading do Clojure
  • Aprendi esse termo como interface fluente. Pipelining é outra coisa

  • O operador de pipeline é um tipo de aplicação parcial, permitindo vincular vários argumentos para criar uma nova função e passar sua saída para outra função

    • Aplicação parcial é muito útil para escrever programas e, algum dia, linguagens (não-Haskell) vão usá-la como base para compor programas
  • Usuários do tidyverse no R já usam isso

  • Pipelining é difícil de depurar. O tratamento de exceções é complicado, então é preciso adicionar ramificações ao pipeline

    • Pipelines só são úteis ao programar o caminho feliz
  • A sintaxe do SQL é desnecessariamente complexa

    • SQL já é uma linguagem de operadores, mas tem muitas restrições por motivos históricos
    • Se fosse permitir nova sintaxe, daria para escrever isso de forma mais simples
    • A sintaxe |> não é expressiva e adiciona ruído visual
  • O autor afirma que "semântica vence sintaxe", mas está focando em preferência sintática

    • Pipelining fica mais difícil de depurar quanto maior a cadeia
    • É crítico em relação a Python, mas não apresenta motivos concretos
    • A definição de "pipelining" não está clara
  • effect-ts permite escrever tanto pipelines quanto código imperativo

    • Há documentação sobre escrever pipelines e usar generators
    • A maior parte da comunidade passou a preferir generators em estilo imperativo
    • Isso parece facilitar a depuração e a manutenção