Saltar al contenido

Pipeline

En esta página

El operador |> pasa el valor del lado izquierdo como primer argumento de la llamada del lado derecho. Esto invierte la lectura respecto a las llamadas anidadas — en lugar de f(g(h(x))), escribes x |> h() |> g() |> f(), siguiendo el orden natural de los datos.

Pipeline simple y con argumentos extra; división en múltiples líneas para pipelines largos.

04-pipe.zolo
Playground
// Feature: Pipe operator `|>`

// Syntax: `value |> function()` — passes the LHS as the 1st arg

// When to use: chain transformations in a data-first flow, without

// nested calls. Replaces `f(g(h(x)))` with `x |> h() |> g() |> f()`,

// reading in natural order.


fn double(x: int) -> int {
  return x * 2
}

fn increment(x: int) -> int {
  return x + 1
}

fn negate(x: int) -> int {
  return -x
}

// Simple pipeline: 5 -> 10 -> 11 -> -11.

let result = 5 |> double() |> increment() |> negate()
print(result)  // -11


// Equivalent without pipe — note how it inverts when you read it:

let r2 = negate(increment(double(5)))
print(r2)  // -11


// Pipe with extra arguments — the LHS goes as the FIRST arg, the

// rest are positional.

fn add(a: int, b: int) -> int {
  return a + b
}

fn mul(a: int, b: int) -> int {
  return a * b
}

// 5 -> add(5, 10)=15 -> mul(15, 3)=45.

let calc = 5 |> add(10) |> mul(3)
print(calc)  // 45


// Pipe split across multiple lines — easier to read step by step.

let pipeline = 100
  |> add(50)
  |> mul(2)
  |> negate()
print(pipeline)  // -300


// Combining with methods via dot — string pipeline.

let clean = "  Hello, World!  ".trim().to_upper()
print(clean)  // HELLO, WORLD!

Cuando el valor encadenado pertenece a otra posición, coloca _ en ese argumento. Una cadena de campo como _.name también crea una lambda compacta de un argumento. Las expresiones más complejas todavía usan una lambda explícita.

Envía un valor al centro de clamp, mapea un campo con _.name y usa una lambda explícita para una expresión booleana.

13-placeholder-pipe.zolo
Playground
// Placeholder `_` in pipes and short lambdas.

fn clamp(lo: int, x: int, hi: int) -> int {
  if x < lo { return lo }
  if x > hi { return hi }
  return x
}

struct User { name: str, age: int }

fn main() {
  // (a) positional placeholder — value flows into the `_` slot, not position 0:

  let v = 150 |> clamp(0, _, 100)
  print(v)                 // 100


  // (b) short lambda — `_.field` in argument position:

  let users = [User { name: "Ada", age: 36 }, User { name: "Bo", age: 17 }]
  let names = users.map(_.name)
  print(names)             // [Ada, Bo]


  // (c) `_` only rewrites when it's the ENTIRE argument (a field/method/

  // index chain headed by `_`). Nested inside an operator expression like

  // `_.age >= 18` it is NOT rewritten — that's out of v1 scope and is

  // rejected as TE132 — so a boolean condition still needs an explicit

  // `|param| ...` lambda:

  let adults = users.filter(|u| u.age >= 18).len()
  print(adults)             // 1

}

El operador &. — "tap" — llama a una función con el valor actual pero descarta el retorno, reenviando el valor original. Es ideal para insertar logs o métricas en medio de un pipeline sin interrumpir el flujo.

Tap entre etapas |> para observar valores intermedios sin alterar el resultado.

05-tap.zolo
Playground
// Feature: Tap operator `&.`

// Syntax: `value &. function()` — calls `function(value)` and

//         FORWARDS the original `value` (ignoring the return).

// When to use: side effects in the middle of a pipeline (logging,

// debug, metrics) without breaking the flow. It is the "spy"

// between `|>`s.


fn double(x: int) -> int {
  return x * 2
}

fn increment(x: int) -> int {
  return x + 1
}

// Function used as a tap — print is the effect, return is dropped.

fn log(x: int) -> int {
  print("  [tap] x = {x}")
  return x
}

// Pipeline with tap between stages.

let r = 5
  |> double() &. log()
  // 10

  // prints "[tap] x = 10", returns 10

  |> increment() &. log()
  // 11

  // prints "[tap] x = 11", returns 11

  |> double()
// 22

print("final={r}")

// expected:

//   [tap] x = 10

//   [tap] x = 11

//   final=22


// Tap also accepts methods via dot — useful for debugging strings.

fn show(s: str) -> str {
  print("  [str] {s}")
  return s
}

// SKIP: pipeline + tap + method call (`|> show().trim()`) is not

// yet parsed; use a temp variable instead.

let cleaned = "  hello  ".trim()
let _ = show(cleaned)
print(cleaned.to_upper())  // HELLO


// Common idiom: measure intermediate length.

// SKIP: `value &. function()` directly on an array literal/var

// currently fails parsing — use the pipeline form instead.

//

// fn count(arr: [int]) -> [int] {

//   print("  [count] len={arr.len()}")

//   return arr

// }

//

// let arr = [1, 2, 3, 4, 5]

// let final_arr = arr &. count()

// print(final_arr)

Desafío

Construye un pipeline de tres pasos con |> que: (1) multiplique por 2, (2) sume 10 y (3) niegue. Agrega un &. log() entre cada paso y confirma los valores intermedios impresos.

Consulta también

Buscar en Zolo

9 resultados

enespt-br