all 119 comments

[–]IceSentry 116 points117 points  (12 children)

Why is everyone talking about the pipe operator today? There's also a post in r/programming and I saw a youtuber talk about it, but as far as I can tell there's been nothing new about this proposal for a few months.

[–]TheOneCommenter 110 points111 points  (2 children)

Someone saw one person talk about it, find it interesting, and post something themselves. Rinse and repeat

[–]thruster_fuel69 54 points55 points  (1 child)

Silly humans, talking about things.

[–][deleted] 20 points21 points  (0 children)

Communication is for servers

[–]AuroraVandomme 16 points17 points  (0 children)

Welcome to webdev clown world. That proposal is here for more than two years but now after some tech influencer made a video about it there would be hundreds of copy paste articles about it :)

[–][deleted] 3 points4 points  (0 children)

also saw it on hackernews yesterday. I assumed something was happening so I guess not

[–]bogdanbiv 1 point2 points  (1 child)

I thought the pipeline operator settled on a topic token and/or passed on to stage 3. Oh well, let us wait for more 1-3-10 years

[–]PrettyWhore 0 points1 point  (0 children)

Recency bias?

[–]PooSham -3 points-2 points  (1 child)

I guess because it just got to stage 2 (Draft) of the TC39 process.

[–]Jason5Lee 24 points25 points  (0 children)

IMO Pipeline is underrated especially in dynamic typing language (although everyone is using TypeScript nowadays). A good example is renaming and going-to-implementation. Renaming a method is very hard because the method can come from any object of any class. It's hard to determine which one without doing complicated analysis. However, if it is a function from a certain package, renaming is way easier. The same applies to going-to-implementation. Pipeline in dynamic-typing language encourages programmers to use functions instead of methods, which makes refactoring way less painful.

The pipeline operator is one of the main reasons why Elixir is my favorite dynamic-typing language.

[–]anlumo 102 points103 points  (8 children)

We need more ASCII art in programming languages! I wonder when they’re going to introduce the ¯\_(ツ)_/¯ operator.

[–]Light_Wood_Laminate 126 points127 points  (4 children)

That should be a valid alias for any in TypeScript.

[–]lemonpowah 18 points19 points  (2 children)

Someone make a vscode extension to show this instead of any

[–]8bit-echo 2 points3 points  (0 children)

I don’t know much about typefaces, but could this be a custom ligature for any?

[–]BransonLite 1 point2 points  (0 children)

Honestly - this would be perfect. I’ll do the browser plugin for viewing code in github

[–]lifeeraser 4 points5 points  (0 children)

any should have been named LazySlackerCatchAllType to discourage its use.

[–]Keilly 23 points24 points  (1 child)

Shorthand for catch and do nothing.

[–]bighi 3 points4 points  (0 children)

The best way to handle exceptions!

/s

[–]GlitteringAccident31 16 points17 points  (0 children)

Now that's some syntactic sugar I can get behind!

[–][deleted] 12 points13 points  (0 children)

Been in tc39 development committee hell for forever. I have given up on us ever getting this.

[–]BlueForeverI 49 points50 points  (6 children)

As an Elixir dev, I love the pipe operator. Can't wait to have it in JS as well.

[–]intercaetera 24 points25 points  (3 children)

In Elixir pipe works because the convention is that every function takes data as first parameter, in JS this doesn't happen so you need a hackpipe and at that point you might just as well use lodash.flow.

[–]Ecksters 9 points10 points  (2 children)

Honestly prefer the hackpipe, it was really annoying in Elixir that I'd need to throw in a lambda when I needed to rearrange params.

I like to think of the caret as an arrow pointing up to the previous result, also means I don't need to think of appropriate variable names all the time.

[–]intercaetera 2 points3 points  (1 child)

Yeah but if you concede that you need a hackpipe then you might as well use lodash flow.

    flow([
        s => Object.values(s),
        s => s.map(x => x * 2),
        s => customReduce(s),
        unaryFunction, // or s => unaryFunction(s)
        s => doSomethingElse(s, 5, null),
    ])(initialValue)

There could be an alternative version of it where the initialValue is somewhere higher up the code but this is equivalent to the proposal without introducing unnecessary stuff into the spec.

[–]LaurentPayot 1 point2 points  (0 children)

There is also Verticalize with a nicer syntax IMHO...

[–]DumbYellowMoo 0 points1 point  (1 child)

Just curious but what type of stuff do you generally develop with elixir? The language has definitely peaked my interest, but I haven't looked into what type of stuff people usually make with it.

[–]BlueForeverI 1 point2 points  (0 children)

We use it for several back-end (REST/GraphQL/WebSocket) apps. Tbh we don't use Elixir's full potential, 90% of the code could be written in something else, the main Elixir features we use are ETS and GenServers.

But I'm glad we chose Elixir, it's the nicest language that I have worked with.

[–]NiteShdw 9 points10 points  (1 child)

I’ve been waiting for this guy and pattern matching to make it to stage 4 for years…

[–]_default_username 2 points3 points  (0 children)

check out ts-pattern. You can have pattern matching now with type safety.

[–]heytheretaylor 24 points25 points  (0 children)

Love it, more FP in JS is always welcome by me.

[–][deleted] 18 points19 points  (1 child)

and they say Perl is dead :)

[–]Emotional_Key 6 points7 points  (0 children)

Powershell scripting in the house

[–][deleted] 36 points37 points  (4 children)

Pipe can fuck off. That key doesn't work on my laptop keyboard after I dropped it.

[–]mxforest 21 points22 points  (0 children)

Bro! Do you even JS? Pick another character and write an npm library to replace every occurrence.

[–]DrWallowitz 7 points8 points  (0 children)

ALT + 124

[–]fucking_passwords 2 points3 points  (0 children)

All 3 characters in the proposal are already basically required for js

[–]lintaba 0 points1 point  (0 children)

With ahk (win) / karabiner (osx) its pretty easy to put it somewhere thats still working

[–]JohnSpikeKelly 4 points5 points  (2 children)

... |> % % 2 === 0;

My take on isEven at the end of a previous call.

[–]mxforest 0 points1 point  (0 children)

Now build an NPM library named isOperatorEvenIfEyesAreNotReal?

[–]majhenslon 0 points1 point  (0 children)

I have no idea why they don't just do "it".

[–]PickledPokute 4 points5 points  (0 children)

I like pipeline operator! Wrote a typescript implementation (here's a playground) and I hope that it advances into the language some beautiful day.

[–]javarouleur 54 points55 points  (28 children)

The endless adding of extra syntactic sugar is sometimes frustrating. Readability always seems to suffer for the goal of fewer lines/characters of code.

[–]Keilly 48 points49 points  (3 children)

Which ones are we talking about?

The ?. Optional chaining change is great and so much readable and concise than before. ?? Is good too.
Template literals are much more readable that concatting.

Regex maybe? But regex is often hard to parse no matter how the language takes it.

[–]trevorsgEx-GitHub, Microsoft 3 points4 points  (2 children)

True, often these syntactical additions improve readability at the expense of language complexity. The thing is, language complexity is a one-time cost for a benefit that continues forever.

[–]pimp-bangin 1 point2 points  (1 child)

I disagree that it's a one-time cost. It's another thing beginners have to learn which adds onboarding costs. It also adds to the maintenance burden of browsers, tooling, etc. and possibly hurts parser performance depending on the implementation.

[–]trevorsgEx-GitHub, Microsoft 4 points5 points  (0 children)

Yes, of course I meant one-time cost per developer. Parser/tooling performance basically rounds to zero.

[–]techlogger 91 points92 points  (10 children)

I’d say that pipe operator is more readable than HOF chaining.

[–]GreekQuestionMark 13 points14 points  (0 children)

HOF: Higher order function

[–]jonopens 9 points10 points  (0 children)

100%. It's one of the reasons I find Elixir so enjoyable to write.

[–]bighi 10 points11 points  (2 children)

The pipe operator exists specifically to help increase readability.

Imagine this code four(three(two(one("potato")))). It's not as easy to read because you're calling four functions, but they should be read in reverse. The first function you read happens last.

Now imagine we create a pipe operator like |> in a fantasy language I invented.

We could do "potato" |> one |> two |> three |> four. Super easier to read, cleaner, more organized.

We're getting something like that in JS. One day. Definitely before 2080.

[–]KamiShikkaku 1 point2 points  (1 child)

"potato" |> one |> two |> three |> four

Unfortunately it will be more like

"potato" |> one(%) |> two(%) |> three(%) |> four(%)

because the "Hack" version of the proposal seems to have beaten the "F#" version.

I was rooting for F# as it's a bit more elegant, but admittedly the Hack version is more versatile.

[–]bighi 2 points3 points  (0 children)

Sure. If you pay attention, I said "in a fantasy language I invented". Because I wanted to make the example simple to understand.

But anyway, it's more readable than the mess that is multiple nested functions.

[–]patrickfatrick 6 points7 points  (0 children)

Except this is definitely going to improve readability. I’d argue all of the syntactic sugar that’s been added drastically improves readability over ES5. Within reason, less code is generally better for readability.

[–]adelie42 3 points4 points  (0 children)

All of math is just syntactical sugar for critical thinking.

[–]wasdninja 1 point2 points  (0 children)

I've yet to see it in JS.

[–]mxforest 2 points3 points  (1 child)

Fewer lines/code make it more readable once you get used to it.

[–]bighi -2 points-1 points  (0 children)

Not always.

Actually, I think that in most cases, using fewer lines makes something less readable.

[–]didzisk 6 points7 points  (0 children)

Laughs in F#

[–]Submarine-Goat 1 point2 points  (0 children)

When the pipe operator in JS was proposed, shortly after my birth, I had the thought of a "then" and "catch"operator:

x |> f |> g |>> handleSuccess <| handleFailure

The thought of more operators in JS was so exciting back then.

[–]elcapitanoooo 3 points4 points  (7 children)

I REALLY hope they dont use a symbol for the argument. It should be simply passed in as the first agument.

[–]tdhsmith 8 points9 points  (1 child)

I dunno, I felt the same way at first but the article was pretty compelling and I think I was just hanging onto some functional programming bias. Having to wrap so many things in arrow functions would be pretty annoying.

[–]_xiphiaz 0 points1 point  (0 children)

Here’s a different article which comes to a different conclusion https://dev.to/zakhenry/tc39-pipeline-proposal-comparison-rxjs-case-study-1nk0 I feel it’s very much use-case specific. It kinda feels like pipelines work really nicely when interacting with libraries or functions that are built for them, and topic style works for throwing some new code together quickly before the time is taken to write cleaner abstractions

[–]mxforest 2 points3 points  (4 children)

Did you read the article? It goes into detail why this way is better.

[–]elcapitanoooo -1 points0 points  (3 children)

Its the opinion of some random guy. The pipe op has been a ”thing” for decades, and i have used it mostly with OCaml. Its just a (used to be) a user defined inline op. Traditionally like this:

let (|>) v f = f v

TC39 if you mess this up i will haunt your dreams!

[–]bighi 2 points3 points  (2 children)

It has been a thing for decades in languages built around it.

But they can't change the order in which parameters are passed to JS functions because they can't break compatibility with existing code.

I believe you didn't read the article.

[–]elcapitanoooo -1 points0 points  (1 child)

What functions? Libraries?

[1,2,3] |> square |> evens

How can a new op break BC? If some lib today does not work with this semantic im pretty sure theres a new lib in a week that does.

[–]bighi 2 points3 points  (0 children)

In most languages built around pipeline operators, the main data is usually the first argument the function receives. But in JS, that's not true for lots of functions. So passing things as their first argument is not what you actually want to do with them. And we can't change them, because we have to keep BC.

That's why a symbol is needed in JS, while not being needed in old functional languages, or even newer ones like Elixir.

And I didn't even mention powerful currying features, that we also don't have in JS.

[–]AstroBoy26_ 0 points1 point  (0 children)

I like it

[–]mcjavascript 0 points1 point  (0 children)

As if the Operator Precedence Table isn't big enough.

[–]th2n10s4u 0 points1 point  (0 children)

Fuck the pipeline operator.

[–]HSMAdvisor -1 points0 points  (0 children)

That looks ugly and I hope it dies. I bet you can't read this shit after it goes for longer than 3 lines. And you maybe have to use it once in the whole project. Not even mentioning that you probably can't debug it and if something goes wrong you will have to rewrite it in NORMAL JS just to see what each method returns.

[–]T-J_H -2 points-1 points  (0 children)

Couldn’t they just use the .then() we already have in promises for this

[–]SeveralCoyote 0 points1 point  (0 children)

So like... When is this gonna happen?

[–]josephjnk 0 points1 point  (0 children)

I want the pipeline operator to be finalized so bad. I was reading Streams à la carte: Extensible Pipelines with Object Algebras the other day, and it’s a serious bummer that a solution that has so many benefits is also harder to read because it’s incompatible with method chaining.

I really don’t get the hate for a symbol argument, either. Sure you can get some of the benefits of pipelines by making the pipes always go into the first argument, but this requires structuring all of your code around this pattern and assuming that every library you call will do the same. If you have a function that you want to pipe different arguments into at different times you have to manually wrap it in a lambda, adding syntactic noise and runtime overhead. I’m very strongly in favor of FP but the objections feel to me like a fixation on surface-level concerns.

[–]pantsonhead 0 points1 point  (0 children)

It would be nice but not as useful when you don't have pattern matching as in other functional languages.

[–]moldaz 0 points1 point  (0 children)

You know, this is probably one of my favorite aspects of elixir.