HN user

timoxley

40 karma
Posts0
Comments21
View on HN
No posts found.

Great stuff. Feature requests: non-wp login, accents, Bar lines, support for non-4/4, swung meter, search by pattern (e.g. write a kick snare pattern, find beats with same kick snare pattern to e.g. find inspiration for hat patterns)

which might promote misunderstanding of the behavior

This isn't a misunderstanding, binary logical operators in JS short-circuit like this by design. I believe && and || returned a boolean value in the past, but were explicitly changed to support this behaviour.

The `err, result` function signature implies the function is an asynchronously executed node-style callback, which can never return anything anyway. Well, it can return something, but nothing internal reads it and there's no way for user code to access the returned value so return becomes only useful for short-circuiting.

Post is referring to async programming in node's callback style (non-promise-based functions executed asynchronously) where return values cannot be captured even if you want to.

The `err, result` signature of the function indicates that it will be executed asynchronously, and thus the return value can't be captured by anything anyway.

The `err, results` params form the signature of a continuation-passing style "errback":

    function(err, results) {
      if (err) // …
    }
It is assumed that this function will be executed asynchronously, and thus it's not possible for anything to consume the return value anyway.

If you want to control the return value, simply return on a new line or use the void operator:

   return void handleError(err)

It depends. Short, dense code can make the code more difficult to understand/change later, while overly bloated code can have the same effect.

I often find inelegant, yet straightforward solutions are generally better options than dense, mathematically pure solutions, simply because inelegant code usually relies on fewer assumptions. Noting that code rarely/never evolves the way we expect it to, apply Occam's razor and strike a balance.

calls at the end can still fail and need handling… You can’t conveniently omit the mess that would be created for checking each of those.

For the purposes of this post, it is assumed that any errors produced in those calls will automatically bubble up the stack to some caller or to the top level. In my experience, most JS code is not written with fine-grained error checking around every expression, if there's any explicit error handling at all. The example code isn't intentionally omitting any mess, rather it appears to me to be fairly typical.

The "handing" at the top is mainly for checking function preconditions. e.g. "does it even make sense to proceed?". Early returns help to decouple precondition checking from the important logic of the function, which IMO makes these types of checks easier to write and maintain and thus more likely to exist.

I'm trying to imagine worst case scenarios here, and at least in an environment like JavaScript, I'm struggling to see how a beginner being overeager with early returns can possibly create anywhere near the same degree of mess as a someone overusing nested if/else statements.

Agreed on early returns being questionable for "two variations of the same concept" though, these days I generally use if/else for situations like that.

... makes case analysis easier ...

...making the code look less complicated than it actually is...

I'd rather emphasize the underlying declarative intent, the state machines, and pre/post-conditions.

These statements are strange to me as I personally see early returns as attempts as achieving exactly these goals. I guess people unroll logic in their head in different ways. "flat" to one may appear "nested" to another and vice versa.

If the return value is important:

    if (err) return void handleError(err)

And in non-promise-based async JS, the return value is almost always lost/useless anyway so `return x` has no effect, might as well repurpose `return` for short-circuiting.

A big gotcha with `&&` as a guard in JS is that it can return any falsey typed value if you don't coerce the guard to a boolean.

e.g.

    const check(cond) => cond && otherValue
If `cond` is falsey, it returns `cond`.

This means the function could return any of: `false`, `undefined`, `null`, '', `0` or `NaN`.

This is a fairly common issue I see with React + JSX:

    <div>{cond && <SomeComponent />}</div>
If `cond` is `false`, `null`, `undefined` or '', everything will be just fine, but if `cond` happens to be a zero or `NaN`, suddenly you have a weird `0` or `NaN` rendering in your page. Oops.

Low cost, much safer guard:

    const check(cond) => !!cond && otherValue