Live data from Hacker News

Pipe Operator (|>) For JavaScript

github.com

251–260 of 437 posts

Re: Pipe Operator (|>) For JavaScript

#251
post #27

Is this: Object.keys(envars) .map(envar => `${envar}=${envars[envar]}`) .join(' ') |> `$ ${%}` |> chalk.dim(%, 'node', args.join(' ')) |> console.log(%); Really better than: console.log(chalk.dim( `$ ${Object.keys(envars) .map(envar => `${envar}=${envars[envar]}`) .join(' ') }`, 'node', args.join(' ') )); That's the real-world example they have (I reformatted the second one slightly, because it looks better to me). N…

I'll bite:

    let _= Object.keys(envars).map(envar => `${envar}=${envars[envar]}`).join(' ')
    _= `$ ${_}`
    _= chalk.dim(_, 'node', args.join(' '))
    _= console.log(_);
This is possible in current JS syntax.

You can also cram it into one line with semicolon:

    let _= Object.keys(envars).map(envar => `${envar}=${envars[envar]}`).join(' ') ;_= `$ ${_}` ;_= chalk.dim(_, 'node', args.join(' ')) ;_= console.log(_);

So it's basically Hack syntax for pipes with just ;_= instead of |> and _ instead of %. And you need to 'mark' the beginning of the pipeline with `let _=`

Additional 'benefit' is that until you leave the scope you can access output of the last pipe through _.

You can always use ;_= for consistency and pre-experess you intent to use the piping in the current scope by doing `let _;` ahead of time:

    let _;

    ;_= Object.keys(envars).map(envar => `${envar}=${envars[envar]}`).join(' ')
    ;_= `$ ${_}`
    ;_= chalk.dim(_, 'node', args.join(' '))
    ;_= console.log(_);
Full disclosure, I hate all of the above but I love Hack syntax with |> and %.

To better confer the direction of the pipe you might even use the letter that is oriented to the right:

    let D;
    ;D= Object.keys(envars).map(envar => `${envar}=${envars[envar]}`).join(' ')
    ;D= `$ ${D}`
    ;D= chalk.dim(D, 'node', args.join(' '))
    ;D= console.log(D);
And if you want to use your pipe as an expression or return it from the function , instead of ; might be better:

    let D;
    return D= take(D) ,D= bake(D) ,D= serve(D);
Surprisingly semicolon auto-insertion doesn't interfere with this:

    let D;
    return D= take(D) 
    ,D= bake(D) 
    ,D= serve(D);

Re: Pipe Operator (|>) For JavaScript

#252

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…

Imagine that you asked someone the question "How do you make a cake?" Which response would be clearer?

1. Gather the ingredients, mix them in a bowl, pour into a pan, bake at 350 degrees for 45 minutes, let it cool off and then separate it from the pan.

2. Get ingredients by gathering the ingredients. Make batter by mixing the ingredients. Make batter in a pan by pouring the batter in a pan. Make a baked cake by baking the batter in the pan at 350 degrees for 45 minutes. Make a cooled cake by cooling the baked cake. Separate it from the pan.

For me personally #1 is more readable because #2 is unnecessarily bloated with redundantly described subjects.

Re: Pipe Operator (|>) For JavaScript

#253

That % syntax is just completely unlike anything else I have seen in JS. As a multi paradigm language, JS typically suffers from whatever programming style is on trend when these features are implemented. We are apparently on the other side of the pendulum now, but I can’t remember the last time I worked with a class and felt like that was right either.

We said the same things when arrow functions got introduced using an outlandishly un-javascripty syntax, as well as when templating strings got introduced using symbols that were the domain of LaTeX. Now they're "just what JS looks like" to both old and new JS devs.

Look past the syntax, because you'll master it quickly enough and 2 years down the line forget it was ever not part of the language: does the actual functionality it introduces improve on what we can do and how we write and understand code or not?

Re: Pipe Operator (|>) For JavaScript

#254
post #169

Earlier quoted context omitted.

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.

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

The thing is I don't think it's all that much more readable. No matter which syntax you use, there's still the same number of "things" going on in a single statement.

I do have to admit I never worked with a language that uses |>, so I'm sure that with increased familiarly with this it would become "more readable" to me, but one has to wonder: just how many calling syntaxes does one language have to support? More syntax also means more potential for confusion, more ways to abuse the language/feature, more "individual programming styles", more argueing over "should we write it like this or that?", more overhead in deciding how to write something, harder to implement the language and write tooling for it, and things like that.

There is always a trade-off involved. The question to ask isn't "would this be helpful in some scenarios?" because the answer to that is always "yes" for practically any language feature. The question to ask "is this useful enough to warrant the downsides of extra syntax?" I'm not so sure that it is, as it doesn't really allow me to do anything new that I couldn't do before as far as I can see. It just allows me to make things that are already too complex a bit more readable (arguably).

Re: Pipe Operator (|>) For JavaScript

#255

Earlier quoted context omitted.

the refactored version of the example is much worse

why? are you of a 'pointfree' opinion? what are your concerns? https://wiki.haskell.org/Pointfree personally i detest pointfree syntax. having intermediate values makes it much easier to step through code with a debugger & see what is happening. and it gives the reader some name for what the thing is, which is incredibly useful context. the enablement of pointsfree styles is one of my main concerns about potential pi…

I think it really depends on the language.

In languages that more easily support repl-driven development (e.g. Clojure), I think this is less of an issue. If you have a handful of pure functions, you can quickly and easily execute them via the repl, so you get a lot of clarity as to what those intermediate values look like even if the functions are ultimately used in a more point-free style.

But on the other hand, this would be a nightmare in C# (what I use in my day job). Sure, you can execute arbitrary expressions while debugging C#, but IMO you can't really achieve the same clarity. I'd rather see intermediate values like you suggest since it's easier while debugging, vs a bunch of nested function calls.

Re: Pipe Operator (|>) For JavaScript

#256

The pipe operator is awesome because you can use it to “extend” objects without messing with their prototypes. Missing String.titleCase ? Write your own! “hello world” |> titleCase

But in the Hack proposal wouldn't that have to be “hello world” |> titleCase (%) I'm starting to like the F# proposal more now.

Consider the example code here in Hack,

  const weather = `https://api.weather.gov/gridpoints/TOP/31,80/forecast`
    |> await fetch(%)
    |> await %.json()
    |> %.properties.periods[0] 
In F# it would be much more verbose,

  const weather = `https://api.weather.gov/gridpoints/TOP/31,80/forecast`
    |> fetch
    |> await
    |> json
    |> await
    |> x => x.properties.periods[0]
    // or |> { properties : { periods: [result] } } => result
Hack will also requires less key strikes for calling functions that have multiple augments.

Re: Pipe Operator (|>) For JavaScript

#257
post #229
post #100

Earlier quoted context omitted.

I'm just using the example they posted in the README as an "before-after". I think that's a reasonable thing to do when evaluating "do I think this would be a good feature?" Blame the author(s) of that document if you don't think it's a good example.

That seems to be missing the point of the document then. Before/after in a design doc isn't "this is a better way to do it".

What is the point then?

Re: Pipe Operator (|>) For JavaScript

#258
post #3

They should have stuck with the F# proposal. The hack proposal just takes one more giant step toward turning JS into Perl. Hack proposal value |> foo(%) for unary function calls, value |> foo(1, %) for n-ary function calls, value |> %.foo() for method calls, value |> % + 1 for arithmetic, value |> [%, 0] for array literals, value |> {foo: %} for object literals, value |> `${%}` for template literals, value |> new Foo…

Consider the example code here in Hack,

  const weather = `https://api.weather.gov/gridpoints/TOP/31,80/forecast`
    |> await fetch(%)
    |> await %.json()
    |> %.properties.periods[0] 
In F# it would be much more verbose,

  const weather = `https://api.weather.gov/gridpoints/TOP/31,80/forecast`
    |> fetch
    |> await
    |> json
    |> await
    |> x => x.properties.periods[0]
    // or |> { properties : { periods: [result] } } => result
Hack will also requires less key strikes for calling functions that have multiple augments.

Re: Pipe Operator (|>) For JavaScript

#259
post #53

Temporary variables are often tedious? I have found that well named temporary variables are the only clear way to comment code without actually writing the comment. The version with temporary variables is much easier to understand without having to read the rest of the code.

This. Temporary variables are the way to go for deconstructing a complex expression like this. Everything is more readable when you put the results of an expression with two to four terms in a well-named variable. Trying to put everything into one giant closed-form expression feels clever and smart, but it's really just getting in the way of the next poor sucker who needs to understand what you were doing. This works…

I wish I could triple-upvote this.

Re: Pipe Operator (|>) For JavaScript

#260

Earlier quoted context omitted.

The issue with taking examples from real-world code & converting them is that there's no guarantee the real-world code is good. It usually isn't, so you're comparing bad with bad. A more aggressive reformulation would be to prefix the original code with const envOutput = Object.keys(envars).map(envar => `${envar}=${envars[envar]}`).join(' '); const argsOutput = args.join(' '); Leaving the example being converted as s…

It's not jarring. It expresses what is the subject that's being processed and what are additional parameters of the processing steps. This allows to keep all parameters of each processing step together and processing steps easily visually separable.

> It's not jarring. It expresses what is the subject that's being processed and what are additional parameters of the processing steps.

Only if the first parameter of the function is the sole subject & subsequent parameters are "additional". Which isn't the case in this example: all params are equal subjects.

Post reply on HN