Working Pipe Operator Today in Pure Javascript
Posted3 months agoActive3 months ago
github.comTechstoryHigh profile
excitedmixed
Debate
70/100
JavascriptProgramming LanguagesFunctional Programming
Key topics
Javascript
Programming Languages
Functional Programming
A JavaScript library implementing a pipe operator using clever syntax manipulation sparks discussion on its utility, readability, and potential for abuse.
Snapshot generated from the HN discussion
Discussion Activity
Very active discussionFirst comment
4d
Peak period
84
96-108h
Avg / period
25.5
Comment distribution102 data points
Loading chart...
Based on 102 loaded comments
Key moments
- 01Story posted
Oct 4, 2025 at 5:54 AM EDT
3 months ago
Step 01 - 02First comment
Oct 8, 2025 at 5:17 AM EDT
4d after posting
Step 02 - 03Peak activity
84 comments in 96-108h
Hottest window of the conversation
Step 03 - 04Latest activity
Oct 9, 2025 at 10:40 AM EDT
3 months ago
Step 04
Generating AI Summary...
Analyzing up to 500 comments to identify key contributors and discussion patterns
ID: 45472119Type: storyLast synced: 11/20/2025, 4:35:27 PM
Want the full context?
Jump to the original sources
Read the primary article or dive into the live Hacker News thread when you're ready.
Overall, cool library.
[0] https://tc39.es/ecma262/multipage/abstract-operations.html#s...
“Aren’t you surprised that this syntax works?” is not praise for a language design.
Serious q: but how does this sentiment change with LLMs? They can pickup new syntax pretty fast, then use fewer tokens...
Otherwise LLMs would excel at writing APL and similar languages, but seems like that’s not the case.
https://metacpan.org/dist/perlsecret/view/lib/perlsecret.pod...
Sure, you can claim that everyone should know this obscure feature when they don’t. But that’s how this language enters C++ territory.
I happened to know it because of how the hyperHTML micro-library works; the author went into great detail about it and a ton of other topics. But my gut would say that the average js dev doesn't know about it.
But then... it's useful for creating component frameworks which... most js devs use. Which doesn't mean they know how they work under the hood. But... a lot of devs I've met specifically choose a framework because of how it works under the hood.
... so... I really have no idea how many people know this. I'm still betting it's less than average.
It's a clever hack. This is Hacker News. Let's try to appreciate clever hacks while here.
https://github.com/tbtlr/def.js
It means having to go to the linked docs (which are automatically pushed to the repo's github pages) to see examples, but I think this is a reasonable tradeoff.
Mutating your inputs is not functional programming. And pipes are effectively compact list comprehensions. Comprehensions without FP is Frankensteinian.
https://github.com/IAmStoxe/PyNQ
You’ve implied what I’ll state clearly:
Pipes are for composing transformations, one per line, so that reading comprehension doesn’t nosedive too fast with accumulation of subsequent operations.
Chaining on the same line is shit for readying and worst for git merges and PR reviews.
other libraries like rxjs use .pipe(f,g,h) which works just fine.
Some OO is fine, just don't make your architecture or language entirely dependent on it. Same with operator overloading.
When it comes to math heavy workloads, you really want a language that supports operator overloading (or have a language full of heavy vector primitives), doing it all without just becomes painful for other reasons.
Yes, the early C++ _STDLIB_ was shit early on due to boneheaded architectural and syntactic decisions (and memory safety issues is another whole chapter), but that doesn't take away that the language is a damn powerful and useful one.
C++23 introduced std::print(), which is more or less the modernized printf() C++ probably should have started with and also includes the functionality of std::format(). Unfortunately, it'll be another 10 years before I can actually use it outside of home projects... but at least it's there now!
| itself still works exactly as before.
https://github.com/gregabbott/chute
https://en.wikipedia.org/wiki/Tacit_programming
I would actually love extension of TS with operator overloading for vector maths (games, other linear algebra, ML use cases). I wouldn’t want libraries to rely on it, but in my own application code, it can sometimes be really helpful.
For one thing, the example isn't the most compelling, because you can:
or That said, there is already:Can you name an example? IME the opposite is a more common complaint: needing to explicitly convert values to arrays from many common APIs which return eg iterables/iterators.
I think what confused me is the passive language: "everything gets converted" sounds (to me) like the runtime or some aspect of language semantics is converting everything, rather than developers. Whereas this is the same complaint I mentioned.
[1]: https://www.amazon.com/Mock-Mockingbird-Other-Logic-Puzzles/...
[2]: https://en.wikipedia.org/wiki/Combinatory_logic#In_computing
[3]: https://leanpub.com/combinators/read#leanpub-auto-the-thrush
Sequences are a common example.
So this:
In pipes this might look like: In functional languages (of the ML variety), convention is to put each operation on its own line: Note this makes for really nice diffs with the standard Git diff tool!But why is this better?
Well, suppose the operation you want is not implemented as a method on `xs`. For a long time JavaScript did not offer `flatMap` on arrays.
You'll need to add it somehow, such as on the prototype (nasty) or by wrapping `xs` in another type (overhead, verbose).
With the pipe operator, each operation is just a plain-ol function.
This:
Is syntactic sugar for: This allows us to "extend" `xs` in a manner that can be compiled with zero run-time overhead.But besides that, I think the better steelman would use methods that dont already exist on the prototype. You can still make it work by adding it to the prototype but... meh. Not that I even liket he proposal in that case.
> You can still make it work by adding it to the prototype
This is exactly what we want to avoid!
Why would you want to avoid that? It's controversial syntactic sugar. Enforcing a convention locally seems ideal.
2. There is a run-time overhead to wrapping
IMO a design goal of programming langauges should be for the most readable code to also be the most performant.
Language features tend to be controversial until they are mainstream.
e.g.
So this:
To your example: is a marked improvement to me. Much easier to read the order of operations and which args belong to which call.https://github.com/lendinghome/pipe_operator#-pipe_operator
[9, 64].map { Math.sqrt(_1) } #=> [3.0, 8.0]
For the first example I would just define a method that uses local variables. They're local so it's not polluting context.
https://dev.to/sethcalebweeks/fluent-api-for-piping-standalo...
In a similar way to the featured project, Chute also uses proxies to work like a pipeline operator. But like in your reply, Chute uses a dot-notation style to chain and send data through a mix of functions and methods.
You might like to see how Chute uses proxies, as it requires no `chainWith` or similar setup step before use. Without setup, Chute can send data through global or local, top-level or nested, native or custom, unary, curried or non-unary functions and methods. It gives non-unary functions the current data at a specific argument position by using a custom-nameable placeholder variable.
The Chute page describes some more of its features: https://gregabbott.pages.dev/chute/
I am wondering if it could be useful for libraries:
npm i aspipes
The F# version of the proposal was probably the simplest choice.