Add the pipe operator: a | f(x) compiles as f(a, x)#28
Merged
Conversation
Implements RFC 0001 (docs/rfcs/0001-pipe-operator.md). The pipe is always on: `|` previously rejected at Compile time as an unsupported bitwise operator, so no compilable expression changes meaning. - desugarPipes (pipe.go) rewrites every `a | f(x, y)` into `f(a, x, y)` between parsing and validation, so the evaluator, Identifiers(), and the fast paths only ever see ordinary call nodes - Non-call right sides are ErrCompile with the RFC's error taxonomy, including "did you mean f(...)?" for bare identifiers and pipe-adjusted signatures for special forms (filter(predicate)) - A bare pipe as the right operand of a comparison is the RFC 3.3 ambiguity diagnostic: `a == b | f()` demands parentheses instead of silently parsing as `a == f(b)` - Optional access composes: `user?.name | upper()` pipes the optional result; `xs | a?.b` is rejected as a non-call right side - Spec, README, llms.txt, examples guide (#13), higher-order patterns guide, and their doc tests updated; fuzz corpus extended with pipe seeds; RFC status updated to implemented (always on) Co-Authored-By: Claude Fable 5 <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements RFC 0001 (roadmap item 7). The pipe operator is always on:
|was previously rejected at Compile time as an unsupported bitwise operator, so no previously-compilable expression changes meaning.Design
desugarPipes(newpipe.go) rewrites everya | f(x, y)intof(a, x, y)between parsing and validation. The evaluator,Identifiers(), the suggester, and the Add evaluator fast paths: cached field plans, reflect-space index chains, typed binary ops #26 fast paths only ever see ordinary call nodes; the pipe has no runtime representation. Special forms compose for free, including the three-arg named-binding shape (orders | filter(o, o.paid)) and lazytry/if.xs | foo→"foo" is not a call (did you mean to write foo(...)?)xs | filter→"filter" is a special form, did you mean to write filter(predicate)?(signature shown with the collection argument dropped, since the pipe supplies it)xs | a?.b→ rejected like any other non-call right side (the optaccess sentinel call is detected so it cannot silently become a 3-arg sentinel)a == b | f()parses asa == f(b)under Go precedence, so expr demands parentheses rather than silently mis-grouping. A pipe on the left (xs | count(it > 1) == 2) is the useful order and needs none.+/-, tighter than comparisons and logicals. Documented with worked examples in the spec.Deviation from the RFC's recommendation
RFC §7.3 recommended shipping behind an opt-in
WithPipeOperator(). Per maintainer decision, the operator is enabled unconditionally instead; the RFC's status header records the override and the rationale (the token never compiled, so the reuse breaks nothing). The §3.3 ambiguity diagnostic and §5/§6 error texts shipped as recommended.Tests
pipe_test.go: rewrite semantics, chaining, all eight iterating forms plustry/if, named bindings, precedence table, ambiguity diagnostic (fires/does-not-fire/parenthesized), error taxonomy, optional-access composition, env callables, templates,Identifiers(),Source(), piped-chain equivalence to nested calls, and a MaxEvalDepth chain boundFuzzCompile/FuzzEvalrun cleanllms.txt, examples guide ([codex] Fix struct tag ambiguity tests for vet #13), higher-order patterns guide, all with matching doc tests;cmd/exprusage example🤖 Generated with Claude Code