Pipeline
Nesta página
O operador |> passa o valor do lado esquerdo como primeiro argumento da
chamada do lado direito. Isso inverte a leitura em relação a chamadas aninhadas
— em vez de f(g(h(x))), você escreve x |> h() |> g() |> f(), seguindo a
ordem natural dos dados.
Pipeline simples e com argumentos extras; divisão em múltiplas linhas para pipelines longos.
// 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!
Quando o valor encadeado pertence a outra posição, coloque _ nesse argumento.
Uma cadeia de campo como _.name também cria uma lambda compacta de um
argumento. Expressões mais complexas ainda usam uma lambda explícita.
Envia um valor para o meio de clamp, mapeia um campo com _.name e usa uma
lambda explícita para uma expressão booleana.
// 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
}
O operador &. — "tap" — chama uma função com o valor atual mas descarta o
retorno, repassando o valor original. É ideal para inserir logs ou métricas
no meio de um pipeline sem interromper o fluxo.
Tap entre estágios |> para observar valores intermediários sem alterar o resultado.
// 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)
Desafio
Monte um pipeline de três etapas com |> que: (1) multiplique por 2, (2) some 10
e (3) negue. Adicione um &. log() entre cada etapa e confirme os valores
intermediários impressos.
Veja também