Hacker News new | ask | show | jobs
by notdonspaulding 1243 days ago
Exactly. As the proposal contemplates this alternative, it claims:

> But there are reasons why we encounter deeply nested expressions in each other’s code all the time in the real world, rather than lines of temporary variables.

And the reason it gives is:

> It is often simply too tedious and wordy to write code with a long sequence of temporary, single-use variables.

Sorry, but...that's the job? If naming things is too hard and tedious, you don't have to do it, I guess, but you've chosen a path of programming where you don't care about readability and maintainability of the codebase into the future. I don't think the pipe operator magically rescues the readability of code of this nature.

The tedium of coming up with a name is a forcing function for the author's brain to think about what this thing really represents. It clarifies for future readers what to expect this data to be. It lets your brain forget about the implementation of the logic that came up with the variable, so as you continue reading through the rest of the code your brain has a placeholder for the idea of "the envVar string" and can reason about how to treat it.

The proposal continues:

> If naming is one of the most difficult tasks in programming, then programmers will inevitably avoid naming variables when they perceive their benefit to be relatively small.

Programmers who perceive the benefit of naming variables to be relatively small need to be taught the value of a good name, and the danger of not having a good name, not given a new bit of syntax to help them avoid the naming process altogether.

The aphorism "There are two hard problems in computer science: cache invalidation, and naming things." is not an argument to never cache and never name things. That's mostly what we software folks spend our time doing, in one way or another.

2 comments

> The aphorism "There are two hard problems in computer science: cache invalidation, and naming things." is not an argument to never cache and never name things.

Sure, it can’t be completely eliminated, but why not do less of a thing that’s hard, when it can be avoided?

Values have a “name”, whether it’s a variable ‘keysAsString’ or the expression ‘keys.join(' ')’. The problem with keysAsString is that you have to type it twice, once to define it and again to use it. It’s also less exact, because it’s a human-only name, not one that has a precise meaning according to the rules of the language. (E.g. a reader might wonder what the separator between the keys was - if you don’t store it in a variable, then the .join “name” tells you precisely right at the site it’s used.) Making the variable name more precise implies more tedium in the writing and reading.

If the value is used twice or more, I would usually say storing it in a well-named variable is preferable, but if it’s cheap or optimizable by the compiler I might still argue for the expression.

This may be a irreconcilable split between different types of thinkers, perhaps between verbal and abstract.

If names are the source of crisis, wouldn’t it be better to define temporary variables without names?

  var [$1, $2] = foo(bar(envars))
  console.log(chalk.bold($2), $1)
Job done, no plumbing needed. Has the same level of semantics as %.
and yet looking through code from the place you work I see something like this

    let field = ve.instanceContext.replace(/(#\/)|(#)/ig, "").replace(/\//g, ".")
Which you apparently claim should be

    const fieldWithHashMarksUnesacped = ve.instanceContext.replace(/(#\/)|(#)/ig, "");
    const field = fieldWithHashMarksUnesacped.replace(/\//g, ".")

https://github.com/mirusresearch/firehoser/blob/46e4b0cab9a2...

and this

    return moment(input).utc().format('YYYY-MM-DD HH:mm:ss')
Which apparently you believe should be

    const inputAsMoment = moment(input);
    const inputConvertedToUTC = inputAsMoment.utc()
    return inputConvertedToUTC.format('YYYY-MM-DD HH:mm:ss')
You've confused method chaining and nesting. The proposal itself says that method chaining is easier to read, but limited in applicability, while it says deep nesting is hard to read. The argument against the proposal by the GP comments is that temporary variables make deep nesting easier to read and do it better than pipes would.
Thanks for taking the time to look and reply.

In your first find, yes, your modification helps me understand that code much more quickly. Especially since I haven't looked at this code in several years.

In that case, patches welcome!

In your second case, as the sibling comment explained, I'm not opposed to chaining in all cases. But if the pipe operator is being proposed to deal with this situation, I'm saying the juice isn't worth the squeeze. New syntax in a language needs to pull its weight. What is this syntax adding that wasn't possible before? In this case, a big part of the proposal's claim is that this sequential processing/chaining is common (otherwise, why do we care?), confusing (the nested case I agree is hard-to-read, and so would be reluctant to write), or tedious (because coming up with temporary variable names is ostensibly hard).

I'm arguing against that last case. It's not that hard, it frequently improves the code, and if you find cases where that's not true (as you did with the `moment` example above) the pipe operator doesn't offer any additional clarity.

Put another way, if the pipe operator existed in JS, would you write that moment example as this?

    return moment(input)
      |> %.utc()
      |> %.format('YYYY-MM-DD HH:mm:ss');
And would you argue that it's a significant improvement to the expressiveness of the language that you did?
|> is for functions the same thing that . is for methods

If you program in object oriented style then . is mostly all you need.

If you program in functional style you could really use |>

I like that the expected variable name has a typo.

Those typos leak out to calling code and it's hilarious when the typo is there 10 years later once all the original systems have been turned off

fieldWithHashMarksUnesacped

The code removes all “#/“ (or just “#” if a slash isn’t there). After that it replaces slashes with dots. How on earth is that “hash marks unescaped”?