Live data from Hacker News

Pipe Operator (|>) For JavaScript

github.com

191–200 of 437 posts

Re: Pipe Operator (|>) For JavaScript

#191

Earlier quoted context omitted.

But that's a symptom of issues with React, not issues with JavaScript. React's declarative model makes it easy to write unreadable spaghetti React declarations that are nested ten levels deep. Nobody should be adding features to JavaScript to encourage that. ("Please, I'm begging you, for the love of sanity... Refactor into more than one component. Just one time. Look, functional components even make that cheap and e…

Highly disagree on two counts: > that's a symptom of issues with React, not issues with JavaScript IMO keeping as much as possible in an expression-context is preferable, even without React, because it simplifies control-flow and avoids mutation. The main problem in this case, as I see it, is that javascript doesn't fully support that style- it could and should have a feature that allows intermediate constants (but n…

I mean, we could refrain from talking about the need to "jump around," but that's the crux of the issue: modern IDEs (like vscode) include "peek" functionality to look at a definition inline. No need to jump around at all. And a thousand-line component has a thousand lines of context it could be pulling in; reasoning about that level of complexity rapidly gets complicated.

If you have some complicated expression to say inline in a React declaration, pull it up to the preparatory layer. If there are performance reasons not to do that, push it down into a subcomponent.

Re: Pipe Operator (|>) For JavaScript

#192
An alternative is to make the pipe operator a simple function application and provide syntax for creating simple pipeline functions.

For example:

    left |> right
Would semantically translate to:

    right(left)
And you could define a pipeline function like so, where the following:

    const myPipeline = @[
        one(@),
        @.two(),
        @ + three,
        `${@} four`
    ]
Would translate to:

    const myPipeline = (value) => {
        const _1 = one(value);
        const _2 = _1.two();
        const _3 = _2 + three;
        const _4 = `${_3} four`;
        return _4
    }
Or:

    const myPipeline = (value) => `${one(value).two() + three} four`;
And you could define the placeholder value name (which would allow nesting):

    const myPipeline = @it [
        one(@it),
        @it.two(),
        @it + three,
        `${@it} four`,
    ]
You'd combine the two syntaxes to get immediately-invoked pipeline functions:

    // Using a modified example from the proposal:
    envars |> @ [
        Object.keys(@),
        @.map(envar => `${envar}=${envars[envar]}`),
        @.join(' '),
        `$ ${@}`,
        chalk.dim(@, 'node', args.join(' ')),
        console.log(@),
    ]
This is better, in my opinion, than building the '%' placeholder syntax into the pipe operator.

Re: Pipe Operator (|>) For JavaScript

#193
post #167

Saw a talk with Douglas Crockford[0] years ago. He said something like: Before JS classes got introduced he asked why they didn't just implement macros for the language. Classes are in fact just syntactic sugar. Just like async/await, and now this proposal. In hindsight he was right. JS would be better off if it did have macros. Much of the whole babel/webpack/react/ts stuff would be just a bunch of macros instead of…

First, syntactic macros are great, and I've often wished for them to exist in javascript (and other languages).

Second, I only trust macros to people who are disciplined to use them wisely.

Third, I've met only a handful of developers I would consider disciplined in this way.

Re: Pipe Operator (|>) For JavaScript

#194
This is cool but it always frustrates me to see these the TC39 focusing on these little improvements to the language instead of taking big bold steps that would have a much more significant impact.

Stuff like types, data binding, reactivity, etc. These would save so many kbs and CPU cycles if implemented natively. The world sorely needs that. God knows how much energy is wasted in sending and processing huge bundles of JS billions of times every day.

Re: Pipe Operator (|>) For JavaScript

#195

Earlier quoted context omitted.

When there are a few they can be really great. But if you need to accurately name every single intermediate thing they can become visual noise that hides what happens.

I struggle to think of real-world examples where I've just needed to chain and chain and chain values of different types more than a handful of times. The claimed need for the pipe operator is this construction: function bakeCake() { return separateFromPan(coolOff(bake(pour(mix(gatherIngredients(), bowl), pan), 350, 45), 30)); } The piped code looks like: function bakeCake() { return gatherIngredients() |> mix(%, bow…

In fact, I'm so fanatical about naming things, I'd probably give the two magic numbers and the return value names as well:

    function bakeCake() {
      const bakeTemperature = 450;
      const bakeTime = 45;  // minutes
      // ... 
      const bakedCake = bake(batterInPan, bakeTemperature, bakeTime);
      // ...
      const finishedCake = separateFromPan(cooledCake);
      return finishedCake;
    }
And I'd not look at a code review which quibbled about the particular names I chose as being a waste of time either. Time spent in naming things well is the opposite of technical debt, it's technical investment. It pays dividends down the road. It increases velocity. It makes refactoring easier. It improves debuggability. It makes unit tests easier to see.

Re: Pipe Operator (|>) For JavaScript

#196

Earlier quoted context omitted.

There's nothing preventing you from not using the pipe for last call or even introducing that rule in your team if you can convince your colleagues it's a good idea or even automate it with the use of a linter. If it's really good rule you can advocate for it at this stage. It might be prudent to use |> % only inside function call parameter or possibly as right hand of an assignment instead of everywhere where parser…

That's almost worse. I think I'd have to break out pen and paper to figure out which of those things end up returning arguments to function "a".

I agree that such restriction would make it worse.

Re: Pipe Operator (|>) For JavaScript

#197
post #167

Saw a talk with Douglas Crockford[0] years ago. He said something like: Before JS classes got introduced he asked why they didn't just implement macros for the language. Classes are in fact just syntactic sugar. Just like async/await, and now this proposal. In hindsight he was right. JS would be better off if it did have macros. Much of the whole babel/webpack/react/ts stuff would be just a bunch of macros instead of…

Mozilla created SweetJS over a decade ago[0]. It added hygenic macros to JS and I'm sure everyone on the TC39 committee is familiar with it.

There's a lot to like about it, but macros in such a complicated language as JS are hard to get right. They'd also potentially lead to huge fracturing in the JS ecosystem with different factions writing their own, incompatible macro-based languages.

Look at JSX for an example. It's actually a subset of a real standard (E4X -- actually implemented in Firefox for a long time), but just one relatively small syntax addition has added complexity elsewhere.

For example, `const foo = (x:T) => x` is valid Typescript for a generic arrow function, but is an error if your file is using JSX.

I like the idea of macros, but I suspect they made the right call here.

[0] https://www.sweetjs.org/

Re: Pipe Operator (|>) For JavaScript

#198

This makes me nervous. In general, I think adding features like this to a mature language is a misstep because it increases the cognitive load of "things you have to know to read other people's code." And that's strictly increases... Since changes like this can't remove previous approaches (for backwards compatibility reasons), we'll now have three syntaxes for function calls? Yuck. Left unchecked, this predilection…

I'm starting to think the entire direction of modern Javascript is one giant yak-shave built on enabling bad decisions. "I like functional programming so I'm going to do that in JavaScript" -> "Now I have a problem because JavaScript is not very good at that, so now let's radically alter JavaScript until it's... well, still not good at it, but it looks like it is, at a glance" (initially through libraries, now alteri…

> watch as their use becomes so hilariously common that it's now painfully obvious that the default behavior is wrong

Hm. :) Hindsight being 20/20, perhaps "synchronous" was a bad default for a language embedded in an application space where the lifeblood is "network communications over unreliable channels."

Still, seemed a good idea at the time(1)

(1) ... at the time, they were doing a cute tech demo, there were alternative scripting languages under consideration, and I don't think anyone expected JavaScript to blow up to become the only viable option.

Re: Pipe Operator (|>) For JavaScript

#199

Earlier quoted context omitted.

When there are a few they can be really great. But if you need to accurately name every single intermediate thing they can become visual noise that hides what happens.

I struggle to think of real-world examples where I've just needed to chain and chain and chain values of different types more than a handful of times. The claimed need for the pipe operator is this construction: function bakeCake() { return separateFromPan(coolOff(bake(pour(mix(gatherIngredients(), bowl), pan), 350, 45), 30)); } The piped code looks like: function bakeCake() { return gatherIngredients() |> mix(%, bow…

Sometimes intermediate values either don't have domain specific meanings or the meaning is obvious from the function name that returns this temporary value.

Then naming it is just noise.

If your bake() function was rather named createBakedCake() than naming returned value bakedCake just increses reader fatigue through repetition.

Same way

Random random = new Random();

in C# is worse than

var random = Random();

Re: Pipe Operator (|>) For JavaScript

#200
post #169

Earlier quoted context omitted.

Do you mind elaborating? I find the refactored version significantly easier to understand than the original. Readability is one of the top priorities for me and I find the original example too clever, in a bad way.

I dislike variables that are used just once. Sometimes they're a "necessary evil", but rarely. For "envStr" it's defensible IMHO as it splits up some of the complexity, but I would rather just use a helper function, which has the same "splits complexity" effect and is re-usable. "styled" seems entirely pointless here.

Extracting `envStr` is definitely the highest impact change for me. I dislike temporary variables too when they don't represent a meaningful intermediary result, but in this case I see them as a lesser evil. I agree that `styled` is more about personal preference.

This is why I'm happy to see the pipe syntax proposal, it avoids unnecessary temporary variables while simultaneously aiding readability.

Post reply on HN