Early Pipeline Sketches
Before Lateralus had a name, it was a notebook full of syntax sketches. Here's what the pipeline operator looked like in its earliest forms.
Attempt #1: Arrow syntax
// July 2023 - first sketch
data -> filter(x > 10) -> map(x * 2) -> sum()
The arrow felt natural but conflicts with function return types in every C-family language. Rejected.
Attempt #2: Double colon
data :: filter(x > 10) :: map(x * 2) :: sum()
Looks clean but conflicts with module/namespace resolution. Rejected.
Attempt #3: Pipe arrow (the winner)
data |> filter(x > 10) |> map(x * 2) |> sum()
Borrowed from F#, Elixir, and the TC39 proposal. Two characters, visually distinct, no conflicts. This is the one.
The naming
"Lateralus" came from the Tool album. The Fibonacci spiral theme felt right for a language about forward flow. Plus, no one had taken the name on npm, PyPI, or GitHub.
What I'd change
Nothing about |>. It's the right choice. But I wish I'd started with a type system from day one instead of adding it six months in. Retrofitting types onto an untyped language is painful.
The argument position debate
Once we settled on |>, the next question was: where does the piped value go? This decision shaped the entire standard library.
// Option A: Explicit placeholder (like Clojure's thread macros)
data |> filter(%, x > 10) |> map(%, x * 2)
// Option B: Always first argument (like F#/Elixir)
data |> filter(x > 10) |> map(x * 2)
// Option C: Curried functions (like Haskell)
data |> filter (x > 10) |> map (x * 2)
We chose Option B. The piped value always becomes the first argument. This is less flexible than a placeholder but far more readable. It also means every standard library function must take its primary data as argument one — a constraint that turned out to be a design advantage, forcing consistent API shapes.
Syntax experiments that failed
Not every idea survived contact with real code. Here are some that didn't make it:
- Implicit pipelines — we tried making every newline an implicit
|>, so you'd just stack function calls vertically. It was unreadable in practice because you couldn't tell what was a pipeline and what was sequential statements. - Pipeline branches — a
|>>operator that would split data into two parallel pipelines. Cool idea, but it introduced non-obvious evaluation order and made debugging nightmarish. - Reverse pipeline — a
<|operator for right-to-left flow. Occasionally useful, but in practice it always made code harder to read. If you need right-to-left, use a let binding. - Pipeline assignment —
data |> transform() |= resultto assign pipeline output. Cute syntax, butlet result = data |> transform()is clearer and doesn't require a new operator.
Influence map
Every language is a remix. Here's what we deliberately borrowed and from where:
- F# — the
|>operator itself, first-argument convention - Rust — ownership semantics,
Result<T, E>, pattern matching, no null - Go — simplicity ethos, fast compilation, single binary output
- Elixir — pipeline-centric design philosophy, pattern matching in function heads
- Zig — comptime evaluation, no hidden allocations, C interop as a first-class goal
- Python — readability-first culture, zero-dependency installer (
pip install lateralus-lang)
The goal was never originality. It was finding the right combination of proven ideas that work together when pipelines are the central organizing principle.
From notebook to language
The first three months were all on paper. Literal paper — a Moleskine notebook that's now held together with tape. The progression was:
- Week 1-2 — syntax sketches for the pipeline operator (covered above)
- Week 3-4 — type system sketches. How do you type a pipeline? Answer: function composition types.
- Week 5-8 — error handling design. Rejected exceptions immediately. Tried Go-style
if errfirst, then moved toResulttypes with|?>. - Week 9-12 — first tokenizer in Python (200 lines). First parser (400 lines). First tree-walk interpreter (600 lines). First program that actually ran.
The notebook still exists. Someday I'll scan it and put it in the papers section as a historical artifact.