Minha sintaxe de programação favorita: "pipelining"
(herecomesthemoon.net)- 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 diffegit blame, o rastreamento das mudanças aparece de forma mais limpa
- Dá para adicionar facilmente uma nova função como
-
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)
- Combina bem com uma estrutura em que a lista de autocompletar aparece ao pressionar a tecla
Pipelining também no SQL?
- Existe a proposta de transformar consultas SQL com
SELECTaninhado 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
SELECTsobe 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 estruturax |> 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
https://github.com/tc39/proposal-pipeline-operator
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.
LINQ é o melhor!
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.
Pensando bem,
elmtambém permite isso.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.
Por favor, coloquem isso também no js |> implorando humildemente
|>é lindo demaisÉ a sintaxe que eu mais odeio
Se o stack trace já estiver só um pouco enrolado, depurar vira um pesadelo
Concordo pra caramba
Comentários do Hacker News
O autor chama isso de "pipelining", mas acho que o termo correto é "method chaining"
Pessoalmente, apoio manter pequeno o conjunto de funcionalidades de uma linguagem e chegar rapidamente a um conjunto de funcionalidades completo
|>do ElixirAs 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
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
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
A sintaxe do SQL é desnecessariamente complexa
|>não é expressiva e adiciona ruído visualO autor afirma que "semântica vence sintaxe", mas está focando em preferência sintática
effect-ts permite escrever tanto pipelines quanto código imperativo