18 puntos por GN⁺ 2025-04-22 | 11 comentarios | Compartir por WhatsApp
  • El pipelining es una función importante en los lenguajes de programación porque mejora la legibilidad y el mantenimiento del código
  • Es una forma de expresar el flujo de datos de izquierda a derecha y de arriba hacia abajo de manera natural
  • En lenguajes como Rust, el pipelining aclara el flujo del código y mejora la productividad del desarrollo gracias al autocompletado del IDE
  • Se aplica en varios lenguajes como Haskell, Elm y SQL, y tanto el patrón builder como el encadenamiento de métodos también se consideran una forma de pipelining
  • Tiene un impacto positivo en la legibilidad, la facilidad de edición, el soporte del IDE y las herramientas de control de versiones (diff, blame)
  • Permite escribir código más conciso y claro que el enfoque de funciones anidadas, por lo que también resulta ventajoso para la colaboración y el mantenimiento

Mi sintaxis de programación favorita: el pipelining

¿Qué es el pipelining?

  • Es una función que permite omitir un argumento de la lista de parámetros al pasar el valor anterior
  • Mejora la legibilidad del código y facilita agregar comentarios
  • Es un estilo sintáctico centrado en los datos que aplica tareas de procesamiento encadenadas de forma secuencial
  • En el código de estilo funcional se usa mucho en forma de encadenamiento de métodos, como .map().filter().collect()
  • En Rust, el siguiente código es un ejemplo representativo:
    data.iter()  
        .filter(|w| w.alive)  
        .map(|w| w.id)  
        .collect()  
    
  • En cambio, si se anidan todas las funciones, queda una estructura que debe leerse de adentro hacia afuera, como esta:
    collect(map(filter(iter(data), |w| w.alive), |w| w.id))  
    

¿Por qué el pipelining es bueno?

  • 1. Legibilidad y mantenimiento

    • Es fácil de leer de arriba hacia abajo → el flujo de datos coincide con el orden en que lo lee una persona
    • Es fácil añadir comentarios en cada línea
    • En líneas largas, resulta conciso y claro sin anidar paréntesis
  • 2. Facilidad de edición

    • Es posible agregar fácilmente una nueva función en una sola línea en medio del flujo, como .map()
    • Incluso en git diff o git blame, los cambios se pueden rastrear de forma limpia
  • 3. Soporte de IDE / LSP

    • Encaja muy bien con una estructura en la que aparece una lista de autocompletado al presionar la tecla .
    • Favorece el análisis estático, que requiere conocer claramente los tipos
    • Para que esto funcione bien, el lenguaje debe estar basado en tipos estáticos (p. ej., Rust, TypeScript)

¿También hay pipelining en SQL?

  • Existe una propuesta para convertir consultas SQL con SELECT anidados a un estilo de pipeline
  • Ejemplo:
    FROM customer  
    |> LEFT OUTER JOIN orders ON ...  
    |> AGGREGATE COUNT(...) GROUP BY ...  
    |> ORDER BY ...  
    
  • Ofrece un flujo más claro y mejor legibilidad que el SQL tradicional
  • Desventaja: al mover la cláusula SELECT hacia arriba, puede ser más difícil identificar el tipo de retorno → se puede resolver

Relación con el patrón Builder

  • Formas como Builder::new().option().option().build() en Rust son una estructura de pipeline típica
  • Al componer configuraciones opcionales mediante métodos, se facilita el seguimiento del código y la gestión de cambios

Mejoras al pipelining en Haskell

  • Operadores como $, &, |> en Haskell permiten usar pipelines en lugar de composición de funciones
  • Comparación antes y después:
    -- 기존  
    checkPalindromes content = unlines $ map (show . isPalindrome) $ lines $ map toLower content  
    
    -- 개선  
    checkPalindromes content =  
      content  
        & map toLower  
        & lines  
        & map (show . isPalindrome)  
        & unlines  
    

Ventajas del pipelining en Rust

  • El encadenamiento de métodos, la inferencia de tipos y la extensibilidad estructural basada en traits encajan muy bien con el pipelining
  • Rust tiene una estructura que parece tomar solo lo mejor de la sintaxis funcional y orientada a objetos, por lo que el uso de pipelining resulta de lo más natural

Conclusión

  • El pipelining no es solo una sintaxis, sino una función clave que influye en el flujo del código, la facilidad de edición y hasta la colaboración
  • En lugar de una anidación como f(g(h(x))), una estructura como x |> h |> g |> f es más amigable para los humanos
  • Bajo la simple regla de “una tarea por línea”, el pipelining es la mejor forma de expresar un flujo natural

“Cada segmento del pipeline recibe los datos principales y realiza una sola tarea. Si al final le das un nombre claro, esa es la estructura de código ideal.”

11 comentarios

 
progdesigner 2025-04-23

Creo que es un contexto parecido a que, en cualquier texto, los saltos de línea y la sangría son importantes para la legibilidad.

 
forgotdonkey456 2025-04-23

¡LINQ es lo máximo!

 
bus710 2025-04-23

Gleam también lo soporta, así que el código queda bastante limpio.

Por cierto, no sé si es porque el texto principal incluye un bloque de código, pero incluso en móvil se ve con el diseño de escritorio.

 
bus710 2025-04-23

Pensándolo bien, Elm también lo permite.

 
galadbran 2025-04-22

Con poca cantidad de datos y código sencillo como en el ejemplo de arriba, me parece que se ve bien y no tiene nada de malo.

Pero cuando poco a poco se empieza a meter código dentro de map()... hay una tendencia a que el código se vaya engordando cada vez más,
y, aunque depende del lenguaje o de la librería de implementación, cuando la cantidad de datos aumenta, en comparación con simplemente ir acumulando o manipulando datos en una estructura de datos para procesarlos, fácilmente puede volverse miles de veces más lento.

Y además me surgió una nueva razón para dejar de preferirlo: vi este artículo en el teléfono y se mantenía el ancho de nivel PC tal cual, así que el tamaño de la letra se volvió diminuto y fue demasiado difícil leer el artículo T.T

Básicamente no lo prefiero, y no hago el esfuerzo de escribir a propósito de esa manera.

 
bichi 2025-04-22

Denme también algo de js |> reverencia, reverencia

 
secret3056 2025-04-22

|> es demasiado hermoso

 
howudoin 2025-04-22

Es la sintaxis que más odio
con que el stack trace esté un poco enredado, depurar se vuelve lo peor

 
cosine20 2025-04-25

Totalmente cierto

 
GN⁺ 2025-04-22
Comentarios en Hacker News
  • El autor lo llama "pipelining", pero creo que el término correcto es "method chaining"

    • Comparación con un pipeline simple de Bash: cada componente se ejecuta en paralelo y los resultados intermedios se transmiten en streaming
    • En Ruby, cada línea se procesa de forma secuencial y se crea un arreglo completo entre cada etapa
    • Hace que depurar sea más difícil, así que últimamente escribo código más explícito
    • El código explícito se ve menos limpio, pero permite inspeccionar fácilmente los estados intermedios
  • Personalmente apoyo mantener pequeño el conjunto de funcionalidades de un lenguaje y alcanzar rápido un conjunto de funcionalidades completo

    • Pero sí desearía que todos los lenguajes adoptaran la sintaxis |> de Elixir
  • Los macros de Lisp ofrecen una solución general que permite decidir el orden de una cadena de llamadas, no solo de operadores encadenados sobre colecciones

    • Por ejemplo, (foo (bar (baz x))) puede escribirse como (-> x baz bar foo)
    • También puede manejar casos con argumentos adicionales
    • Para más detalles, consulta la guía de macros de threading de Clojure
  • Aprendí este término como interfaz fluida. Pipelining es otra cosa

  • El operador de pipeline es una especie de aplicación parcial, ya que permite enlazar varios argumentos para crear una nueva función y pasar su salida a otra función

    • La aplicación parcial es muy útil para escribir programas, y algún día los lenguajes (no Haskell) la usarán como base para componer programas
  • Los usuarios de tidyverse en R ya usan esto

  • El pipelining es difícil de depurar. El manejo de excepciones es complicado, así que hay que agregar ramificaciones al pipeline

    • El pipeline solo es útil cuando se programa el camino feliz
  • La sintaxis de SQL es innecesariamente compleja

    • SQL ya es un lenguaje de operadores, pero tiene muchas limitaciones por razones históricas
    • Si se permitiera una sintaxis nueva, podría escribirse de forma más simple
    • La sintaxis |> no es expresiva y añade ruido visual
  • El autor afirma que "el significado le gana a la sintaxis", pero se enfoca en preferencias sintácticas

    • El pipelining se vuelve más difícil de depurar cuanto más larga es la cadena
    • Es crítico de Python, pero no da razones concretas
    • La definición de "pipelining" no está clara
  • effect-ts te permite escribir tanto pipelines como código imperativo

    • Ofrece documentación sobre cómo escribir pipelines y usar generadores
    • La mayor parte de la comunidad terminó prefiriendo los generadores con estilo imperativo
    • Parece que son más fáciles de depurar y mantener