En Elixir, el operador |> pasa el resultado de una expresión como el primer argumento de la siguiente función. Ya lo explicamos en el post anterior.
" hello "
|> String.trim()
|> String.upcase()
Resultado: "HELLO"
Este diseño promueve una lectura fluida del código, eliminando la necesidad de paréntesis anidados.
F#, un lenguaje funcional inspirado en ML, también tiene un operador pipe |> con un propósito similar al de Elixir.
" hello "
|> String.trim
|> String.uppercase
El operador en F# permite que el flujo de datos sea explícito, facilitando la composición de funciones.
Python no tiene un operador pipe nativo, pero existen bibliotecas que lo emulan, como `pipe` o `toolz`. Sin embargo, sin bibliotecas adicionales, puedes lograr algo similar con reduce:
from functools import reduce
data = " hello "
result = reduce(lambda acc, fn: fn(acc), [str.strip, str.upper], data)
print(result) # HELLO
Con una biblioteca como pipe:
from pipe import Pipe
result = " hello " | Pipe(str.strip) | Pipe(str.upper)
print(result) # HELLO
JavaScript aún no tiene un operador pipe oficial, pero hay una propuesta en desarrollo en el comité TC39 (etapa 2 al momento de escribir). Con esta propuesta, el pipe se usa de la siguiente manera:
" hello "
|> (x => x.trim())
|> (x => x.toUpperCase());
Por ahora, puedes emularlo con funciones:
const pipeline = (...fns) => x => fns.reduce((v, f) => f(v), x);
const result = pipeline(
x => x.trim(),
x => x.toUpperCase()
)(" hello ");
console.log(result); // HELLO
Scala no tiene un operador pipe nativo, pero es posible definir uno:
implicit class PipeOps[T](val value: T) extends AnyVal {
def |>[R](f: T => R): R = f(value)
}
val result = " hello "
|> (_.trim)
|> (_.toUpperCase)
println(result) // HELLO
En C#, aunque no existe un operador pipe, los métodos de extensión de LINQ se comportan de manera similar:
string result = " hello "
.Trim()
.ToUpper();
Console.WriteLine(result); // HELLO
El concepto detrás del operador pipe (`|>`) es universal: facilita la composición de funciones y mejora la legibilidad. Aunque su implementación varía entre lenguajes, su propósito sigue siendo el mismo: transformar datos paso a paso de manera clara y concisa.