VIP-23: the pipe operator |>
Status: accepted by Will, 2026-10-28, under his standing approval ("assume I accept now. I will interrupt you if I need to").
Decision
const n = fetchUser(id) |> retry(%, policy) |> timeout(%, "1 second")
try n- Its Effect TS is nested calls, with each topic evaluated once into a temporary:
const t1 = fetchUser(id); const t2 = retry(t1, policy); const n = timeout(t2, "1 second"). |>is exactly TC39's Hack pipe operator, pinned to a dated snapshot of the proposal, likedo(VIP-2) andmatch(VIP-7).%is the topic: the left side's value, evaluated once. The topic-versus-modulo grammar is TC39's, unchanged.- Effect's
pipe(x, f, g)function remains available through VIP-14. - Ambiguity: none beyond TC39's own grammar.
- Amended 2026-10-29: the pinned snapshot.
|>is pinned totc39/proposal-pipeline-operatorcommit5ac4dfd624e68b649e6f947885bf5ef67bac19f4, the head on 2026-10-28 (UTC), vendored intc39-pipeline-operator/, as pattern matching is pinned. Decided by the agent on 2026-10-29 under Will's rule "when I state a principle, the agent derives the concrete rule and acts; I can override later" (decided detail 52). - Amended 2026-10-31: arrows at the right edge. An
EffectArrowis an arrow for the pinned pipe-body restriction. The input of aPipeExpressionmay not end in an opencatcharrow handler, so the|>belongs to the handler's body; parentheses, a closed handler and a block-bodied arrow end the handler. Both rules remove second derivations, and neither rejects a program with a greedy parse. Decided by the agent under Will's rule "when I state a principle, the agent derives the concrete rule and acts; I can override later" (decided detail 246).
History
Old findings concerned a topic that ran Effects implicitly. Under VIP-5 a call never runs anything, so they don't apply.
Prior art
TC39's Hack pipes (stage 2), Hack, F#'s and Elixir's |>.
-
Clarified 2026-11-03: arrows at the right edge. The arrow-body covering restriction includes
EffectArrow, as it includesAsyncArrowFunction. A pipe input cannot end in an open arrow catch handler, recursively through a pipe body: the following pipe belongs to that handler's concise body. Parentheses or a block-bodied handler close that boundary. -
Clarified 2026-11-03: pipe diagnostics. Adopted pipe grammar and early errors without a more specific code use
EK2301, including a missing topic and a whole bare plain,asyncoreffectarrow body. Parenthesize the arrow,x |> (() => %). This follows VIP-34's diagnostic ownership rule and changes no pipe admission or evaluation rule.