Language Policy

Pipelines & Placeholders

Canonical grammar, semantics, constraints, and deferred boundaries for Pipelines & Placeholders.

A pipeline evaluates its left side once and then applies one unambiguous placeholder, insertion, callable, or property rule; formatting never changes which value flows.

Policy

For left |> right, left is saved before any right-side subexpression. If _ appears in a call argument position, every valid placeholder receives that saved value and implicit insertion is disabled. Without placeholders, a call receives the saved value as its first positional argument; a callable value is invoked with one argument; .field reads that field from the saved value. Pipelines associate left to right.

Specified behavior

The placeholder binds to its nearest containing call and ordinary call evaluation then proceeds. Multiple placeholders in the same right side receive the same saved left value. Named arguments still follow all positional/spread arguments, and generic call checking happens after placeholder or insertion binding. Wildcard _ in a pattern remains a discard and is unrelated to pipeline replacement.

Constraints and loud decline

A bare _, _ as callee/member/field label, a non-call expression that is not callable, named-before-positional arguments, and optional-property pipe sugar |> ?.field are rejected. The pipeline never evaluates its left side once per placeholder and never inserts an extra argument when a placeholder exists.

Deferred boundary

User-defined pipe operators, implicit async lifting, automatic error propagation, partial application syntax, optional pipe-field sugar, and broad composition are not part of the profile. Function composition >> exists at SPEC level but canonical public docs use |> or named functions.

Worked example

TOPAZ
function double(value: int) -> int { value * 2 }

let values = [1, 2, 3]
let doubled = values |> map(_, double)
print("{doubled}")