Use a pipeline when a result should visibly flow into the next operation.
left |> right evaluates left once, saves that value, and then chooses one
well-defined way to supply it to right. A placeholder _ marks the exact
call-argument position that receives the saved value.
Start with a self-contained pipeline
Save this as pipelines-placeholders.tpz:
function add(value: int, amount: int) -> int {
value + amount
}
function multiply(left: int, right: int) -> int {
left * right
}
function equal(left: int, right: int) -> bool {
left == right
}
let result = 5
|> add(2)
|> multiply(_, 3)
let repeated = result |> equal(_, _)
print("{result} {repeated}")Check and run it:
topaz check pipelines-placeholders.tpz
topaz run pipelines-placeholders.tpz
The output is:
21 trueThe first stage has no placeholder, so the saved 5 is inserted as the first
argument: add(5, 2). The second stage says exactly where the saved 7 goes:
multiply(7, 3). In the final pipeline, both placeholders receive the same
saved 21, so the call is equivalent to equal(21, 21). The left side is not
evaluated again for the second placeholder.
Choose the right-hand shape
| Right side | Meaning |
|---|---|
value |> call(other) | Insert value before all explicit positional, spread, and named arguments |
value |> call(_, other) | Replace every valid _ argument with value; do not also insert it |
value |> callable | Call the callable with value as its one argument |
value |> .field | Read field from value |
Pipelines associate from left to right, so each stage receives the completed
value from the stage before it. The placeholder belongs to its nearest
containing call. A _ inside a pattern is instead a wildcard that discards a
matched value; the two roles share a token but not a scope.
Multiple placeholders are valid when each appears in a call-argument position.
They all receive the same saved left value. Placeholder replacement takes
priority: once a valid _ exists on the right, Topaz does not insert an extra
first argument.
Common correction
A bare _ is not a value. It cannot be the whole pipeline right side, a
callee, a member name, or a field label. Put it inside the argument list of the
call that should receive the piped value.
Optional-property pipe sugar such as value |> ?.field is not supported. Use
ordinary optional chaining before or inside an explicit lambda. Named
arguments must still follow positional and spread arguments after pipeline
binding. A right side that is neither a call, a callable value, nor .field
is a static error.
Pipelines do not add automatic Result propagation, partial application,
asynchronous lifting, or a user-defined pipe operator. Use postfix ?
explicitly for Result propagation and concurrent explicitly for bounded
concurrent work.
See Operators & Expressions for precedence, Functions & Generics for callable values, and Collections & Comprehensions for collection-producing stages.