Caspian Pipe Operator Design GitHub issue

Overview GitHub issue

vibecode
{"vibecode": {
    "section": "overview",
    "role": "introduces the Caspian pipe operator for chaining in execution order",
    "key_concepts": ["pipe_operator", "execution_order", "chaining", "nested_call_alternative"]
}}

Caspian introduces a pipe operator to allow chaining operations in execution order, rather than nested call order.

This provides a more readable and intuitive alternative to deeply nested expressions.


Basic Pipe Operator GitHub issue

vibecode
{"vibecode": {
    "section": "basic_pipe_operator",
    "role": "defines the | operator: passes left result as first and only arg to right",
    "key_concepts": ["pipe_operator", "single_argument", "desugaring", "a_pipe_b"]
}}

Syntax GitHub issue

caspian
a | b

Semantics GitHub issue

The pipe operator passes the result of the left-hand expression as the first positional argument to the right-hand expression. The right-hand side may also accept additional positional or named arguments at the call site; the piped value occupies the first positional slot and the rest of the arguments are bound normally.

caspian
a | b

desugars to:

caspian
b(a)

With additional arguments at the call site:

caspian
$list | sort('asc')
$list | filter(min: 5, max: 10)

desugar to:

caspian
sort($list, 'asc')
filter($list, min: 5, max: 10)

Same shape as Elixir's |>, F#'s |>, R's %>%.


Chaining Pipes GitHub issue

vibecode
{"vibecode": {
    "section": "chaining_pipes",
    "role": "shows how multiple | operators desugar to nested function calls",
    "key_concepts": ["pipe_chain", "sequential_execution", "nested_call_desugaring"]
}}

Multiple pipes can be chained to represent sequential execution:

caspian
&a |
&b |
&c

desugars to:

caspian
&c(&b(&a))

Example: Method Calls GitHub issue

vibecode
{"vibecode": {
    "section": "example_method_calls",
    "role": "illustrates pipe chaining with method calls on objects",
    "key_concepts": ["method_call_piping", "execution_order_readability"]
}}

Pipes work naturally with object method calls:

caspian
&baz |
&bear |
$bar.gup

desugars to:

caspian
$bar.gup(&bear(&baz))

This allows writing code in the same order as execution.


Design Principle GitHub issue

vibecode
{"vibecode": {
    "section": "design_principle",
    "role": "states the core design rule: pipes express data flow in execution order",
    "key_concepts": ["data_flow", "execution_order", "single_input_per_stage"]
}}

Pipes express data flow in execution order, not call nesting.

Each stage receives exactly one input: the result of the previous stage.


Null-Safe Pipe Operator (|&) GitHub issue

vibecode
{"vibecode": {
    "section": "null_safe_pipe_operator",
    "role": "documents the |& operator for null propagation through a pipe chain",
    "key_concepts": ["|&_operator", "null_propagation_mode", "null_safe_chaining", "once_set_all_subsequent"]
}}

Motivation GitHub issue

Caspian supports null-safe chaining in method calls:

caspian
$foo.bar&.gup.bear

This stops evaluation if bar returns null.

The pipe system introduces a similar concept.


Syntax GitHub issue

vibecode
{"vibecode": {
    "section": "null_safe_syntax",
    "role": "shows the |& operator syntax",
    "key_concepts": ["|&_syntax", "null_safe_pipe_form"]
}}
caspian
a |& b

Semantics GitHub issue

vibecode
{"vibecode": {
    "section": "null_safe_semantics",
    "role": "explains that |& enables null propagation mode for all subsequent pipe stages",
    "key_concepts": ["null_propagation_mode", "remainder_of_chain", "sticky_null_safe"]
}}

The |& operator enables null propagation mode for the remainder of the pipe chain.

Once |& is used, all subsequent pipe stages automatically become null-safe.

Example GitHub issue

caspian
&foo |&
&bar |
&gup

is equivalent to:

caspian
&foo |&
&bar |&
&gup

Execution Model GitHub issue

vibecode
{"vibecode": {
    "section": "execution_model",
    "role": "shows the desugared if-null-return expansion for null-safe pipe chains",
    "key_concepts": ["null_check_expansion", "return_null_early", "desugared_form"]
}}
caspian
&foo |&
&bar |
&gup

desugars to:

caspian
let x = &foo
if x == null
    return null

let y = &bar(x)
if y == null
    return null

return &gup(y)

Design Rule GitHub issue

vibecode
{"vibecode": {
    "section": "null_safe_design_rule",
    "role": "states the rule that |& once used propagates null through all subsequent stages",
    "key_concepts": ["once_propagates_all", "no_repetition_needed", "clear_intent"]
}}

Once |& appears in a pipe chain, all subsequent pipes propagate nulls. This avoids repetition while keeping intent clear.


Summary GitHub issue

vibecode
{"vibecode": {
    "section": "summary",
    "role": "quick reference table for pipe operator meanings",
    "key_concepts": ["pipe_operator_table", "|", "|&"]
}}
Operator Meaning
` `
` &`

Future Considerations (Optional) GitHub issue

vibecode
{"vibecode": {
    "section": "future_considerations",
    "role": "lists intentionally deferred pipe features for possible future design",
    "key_concepts": ["placeholder_arguments", "multi-argument_pipe", "pipe_grouping", "deferred_design"]
}}
These are intentionally deferred to keep the initial design minimal and predictable.

© 2026 Puck.uno