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 basicall…
Pipe Operator (|>) For JavaScript
351–360 of 437 posts
Re: Pipe Operator (|>) For JavaScript
#352Earlier quoted context omitted.
This actually surprises me! One habit introduced to my current team by a former co-worker involves having even more intermediate keys than that: const sensitiveEnv = [...]; const envKeys = Object.keys(envars) const safeKeys = envKeys.filter(envar => !sensitiveEnv.includes(envar)); const safeEnv = safeKeys.map(envar => `${envar}=${envars[envar]}`).join(' '); const styled = chalk.dim(`$ ${envStr}`, 'node', args.join('…
I just find it easier "thing" that happens is one self-contained statement, if that makes sense. Makes it easier to see what does what. I don't think one way is "better" or "worse" btw; all I can say to my brain, I find it harder to follow. This is what can make programming in a team hard. I'm also one of those people that likes single-letter variables. I know some people hate it with a passion, but I find it very co…
I agree with your remarks, there's no right or wrong, it's like tabs and spaces.
Btw I'm also not smart enough for Haskell, but it hasn't stopped me so far ;)
Re: Pipe Operator (|>) For JavaScript
#353Is 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…
Yes! A hundred thousand times yes!
I have not seen this syntax in JavaScript before, but just by having the vague notion that it's pipe-like, I was able to generally understand what was happening within seconds of reading it. I'd have to read up on the syntax a bit to confidently write code in this style, or perhaps to fix a bug (does "${%}" do what I think it does) but I can quite literally comprehend the author's intent almost at almost the same speed as I can read.
1. get all the keys of envars.
2. convert every key into a "var=value" format.
3. put a space between them all
4. stick a dollar sign in front of the whole thing
5. no clue what the `chalk` library is for?
a. this *appears* to prefix a "node ${args}" call with the previously-created environment variable bits
b. that tracks with what we've seen so far
c. close enough for now
6. log the whole thing
Note that even without knowing what chalk is or does, the flow of everything makes it extremely clear what exactly the high-level outcome is supposed to be. We're building up a string like "$ FOO=bar BAZ=qux node --arg thing --arg2 more_args". We're doing something fancy with it that I don't quite know about just yet, but the above knowledge makes it very easy to fill in that gap.With the second one, I have to construct a tree in my head
1. console.log…
a. the result of chalk.dim, which is
i. all the env vars
ii. mapped to key=value format
iii. joined by a space
b. ^ actually do chalk.dim on that thing above
i. sorry, back up, there were some additional arguments
c. ^ actually do chalk.dim on the above with 'node' and space-separated args
i. I think this concatenates them?
ii. double-check [1.a] to confirm
iii. did I miss `args` defined somewhere in [1.a]?
A. no, it's apparently inherited from scope
2. ^ actually log all the above
a. wait is this a correct reading, based on reassembling the above?
The confusion is compounded by not knowing the details of chalk. I have to jump backwards and reason about what the result of a non-linear chunk of steps is to make sure my guess is consistent.I have no opinion on the merits of this particular syntax, its implementation details, or in comparison to alternate proposals of similar ideas. I'm sure there's worthwhile debate to be had on those details. But from a high level, I'm a fan. My head is not a meat-based tree traverser and I'm guessing most people's isn't either. Human brains are big fans of linear narratives. While I love movies and shows like Memento and Westworld, this kind of disjoint storytelling is quite literally done for the purpose of generating confusion and not for promoting comprehension.
Also, there may already exist better ways of expressing this particular example linearly and succinctly. If there is, I'd probably prefer that. Worst-case scenario you can always deconstruct nested function calls into sequential variable assignments, and maybe that's the "best" answer here instead of new syntax. But is an approach that can be understood linearly from start to finish clearer than one that requires mental tree-walking? Yes. Yes yes yes yes yes.
Re: Pipe Operator (|>) For JavaScript
#354Temporary 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.
I often find flow-crutches like the one described in this proposal more confusing to decipher than plain old fashioned, well thought out code.
Lambda (=>) expressions in C# and closures in JavaScript are others I sometimes find myself pausing at to make sure I'm interpreting correctly.
I always figured it's just because I'm an older programmer and haven't used the new language features enough for them to become intuitive. I do acknowledge there are use cases where they're a perfect fit for the pattern in which you're coding.
But I feel like they're too-often taken as a shortcut to dump a bunch of operations in one place when it would be more readable to structure into well-organized functions that logically group concerns.
It's not that I don't like syntactic sugar to make code more concise, I just think languages need to remain judicious about how many different ways they dole out to accomplish the same task before they start to risk 'rotting their teeth'. Gotta keep striving for elegance - as you renovate over time it can get harder to keep the bar high.
Re: Pipe Operator (|>) For JavaScript
#355Earlier 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.
Those variables help to document intent by naming the intermediate values. They also make step-debugging more convenient. In languages with type declarations, they also serve to inform about the type of the intermediate value, which otherwise is invisible in a pipe sequence.
Re: Pipe Operator (|>) For JavaScript
#356Re: Pipe Operator (|>) For JavaScript
#357Earlier quoted context omitted.
The Hack proposal is horrible imo because it doesn’t look like JS anymore. The F# proposal is 99% of the benefit whilst being actually approachable.
I think we should have BOTH. Use |> for the Hack proposal and -> for F# -style.
Re: Pipe Operator (|>) For JavaScript
#358I hope Records & Tuples[0] land before this does. It would have meaningful and far reaching positive effects for the language, without much controversy. Like most of these things, it takes about 5-7 years for it to permeate through enough of the engines to be meaningfully useful in the day to day of web developers (node / deno typically 12-18 months tops). It would drastically speed up existing code once wide adoptio…
The one I really want is “do expressions”. I also can’t understand why anyone wants private fields over these kind of improvements. Lack of private fields in JS has literally never caused a big for me in 15 years of JavaScript development, but I have to use mutable variables and ugly if-else chains to 3 case assignment all the time!
const isSomething = (() => {
switch (...) {
case ...:
return ...
}
})()
They are a bit ugly but the do wonders at avoiding `let`.Re: Pipe Operator (|>) For JavaScript
#359Re: Pipe Operator (|>) For JavaScript
#360Saw 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…
Wouldn't that just trade compatibility churn against running the transpilers on client side in javascript, making it even slower to execute? Moving this part of the execution on the developer side seems like a good choice to me.