I love the pipe operator in Elixir!
Pipe Operator (|>) For JavaScript
241–250 of 437 posts
Re: Pipe Operator (|>) For JavaScript
#242Is 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 also feel this: >> In the State of JS 2020 survey, the fourth top answer to “What do you feel is currently missing from JavaScript?” was a pipe operator. > Is the wrong way to go about language design. Let's call it Signor Rossi language design… "Signor Rossi cosa vuoi? … E poi, e poi, e poi" ( Viva la felicità by Franco Godi [1]) [1] https://www.youtube.com/watch?v=UrKKMtjNWCI
Re: Pipe Operator (|>) For JavaScript
#243Earlier 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.
Re: Pipe Operator (|>) For JavaScript
#244Re: Pipe Operator (|>) For JavaScript
#245Earlier 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.
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(' '));
console.log(styled);
In the beginning I wasn't a fan of it, as I do a lot of Haskell (and have point-free idioms on the tip of my fingers), and it's obviously unnecessary, as you said yourself. But with time I learned to appreciate this kind of function for its simplicity and consistence.Now, of course, with a pipe operator (or other similar constructions) you can get the consistency without the intermediate names.
Re: Pipe Operator (|>) For JavaScript
#246I don't understand why you can't just use temporary variables. The article mentions mutation is bad, but what actually happens is that the name gets reassigned. No value is mutated. That brings me to something I really want in JS, actual unmutable values. If you use `const x = new SomeClass()`, you cannot reassign it, but you can change fields. The first time I encountered `const`, I thought it did the opposite. It w…
That sounds like a fundamental mis-understanding. Variables do not hold objects, they hold references to objects.
const foo = {};
let bar = foo;
foo and bar hold references to the same object. They do not hold the object themselves. foo's reference can not be changed. It's const. bar's reference can. But the object is independent of both variables.If you want the object itself to be unmodifiable there's Object.freeze.
const foo ...
makes foo const. If you wanted a shortcut for making the object constant (vs Object.freeze) it would be something like let foo = new const SomeObject()
This doesn't exist but it makes more sense than believing that `const foo` some how makes the object constant. It only makes foo constant (the reference).Re: Pipe Operator (|>) For JavaScript
#247Is 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…
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…
Re: Pipe Operator (|>) For JavaScript
#248Earlier quoted context omitted.
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 agree that (1) named intermediate values are sometimes more readable ... though I have examples where it's very hard to come up with names and not sure it helped (2) debugging is easier. For (2) though, this IMO is a problem with the debugger. The debugger should allow stepping by statement/expression instead of only by line (or whatever it's currently doing). If the debugger stopped at each pipe and showed in valu…
Re: Pipe Operator (|>) For JavaScript
#249Earlier quoted context omitted.
...so only the first usage of `%` counts as a replacement? What if I need the value to be replaced multiple times, like this: |> `${%.id}: ${%.friendlyName} ${%.url}` I'm surprised they aren't going with an idiom like `$1`, `$2`, etc or something like in other languages that have "magic" lambda parameters.
> ...so only the first usage of `%` counts as a replacement? Hopefully not because there’s no reason to: in the same way you can use + or - as prefix or infix, % as value and % as binary operator are not ambiguous. % % % should not be an issue, though it’s useless and not exactly sexy looking. > I'm surprised they aren't going with an idiom like `$1`, `$2`, etc That makes no sense, $1, $2, and $3 are different parame…
|> `${$3.id}: ${$1.friendlyName} ${$2.url}`
>makes absolutely no sense.That's not what I was saying. I was saying that using `$1`, `$2`, and `$3` _would be different parameters, which would be good at helping disambiguate_.
That would enable this, from my example:
|> `${$1.id}: ${$1.friendlyName} ${$1.url}`
while also enabling something like this: |> `$1.indexOf($2)`
...whereas just sticking with the single `%` means you _can't_ disambiguate, and that if they instead try to allow disambiguation by deciding that the first `%` is `$1`, and the second `%` is `$2` (and so on), then now you can't use the template-string example I gave.Having unique "magic scope variables" at least allows you the flexibility to handle non-unary use-cases.
Either way, this is another case of "every lexer/parser has to be riddled with special cases" to handle "is this `%` a fancy-pipeline-identifier, or is it an operator?"