Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Aggressive coercion in an attempt to execute clearly faulty code is exactly the problem.


The most common mistake I see when people talk about JS quirks is to assume that this kind of feature is always about fault tolerance rather than convenience.

For example, many languages treat conditions as "if nonzero". From a certain perspective, you could argue that

  if (i--) {
is "clearly faulty code".

From another perspective, you would say it's a shorthand whose meaning is obvious to anyone familiar with the rules of the language.

In my view, JavaScript's sin is that its rules are complicated, and it's difficult to statically analyze, so tools intended to guard against its pitfalls can only do so much.

Whether or not the complicated rules are about faulty code is pretty irrelevant. ASI is an error correction mechanism, but its pitfalls are easy to detect, so in modern environments it doesn't matter. The behavior of comparison operators seems to me like more of a convenience feature, but it's still a problem; the rules are easy to forget, and only a very draconian linter rule can protect you.


Honestly, I like implicit coercion of empty stuff into false. Yes, I do agree it makes the code more legible.

That said, objectively it doesn't gain that much. It may be that the cost of having any kind of implicit coercion is bigger than such gain. Implicit numeric coercion is another topic to think about, it is also hard to be sure if it is a net gain.


But not all code that looks faulty is faulty. I know plenty of competent people who have used the numeric properties of undefined and null directly with numeric operators knowing exactly what they're doing. Likewise there is a natural association between nonzero and true, zero and false, which is very useful (multiplying by a boolean, accumulating a list of booleans in a collection of records to get a count).

If you're using JavaScript, I encourage you to embrace the dynamic, coercive funky nature of the language. There is a twisted logic to each twisted feature.


But the code using twisted features is hard to maintain afterward.

You will have to put comments around them just to be sure the next guy (it might even be the author himself) doesn't waste its time understanding what the hell the code is doing.


> But the code using twisted features is hard to maintain afterward.

    let a = 0;
    for (const record of records)
      a += record.bool;
What's so bad about this? (aside from mutable accumulator, but that can be restricted to one scope). The pattern is basically directly lifted from C, where there's thankfully no such thing as a boolean type. If anything, the solution is to fold Boolean and null into Number to begin with.

> You will have to put comments around them just to be sure the next guy (it might even be the author himself) doesn't waste its time understanding what the hell the code is doing.

I sincerely hope that anyone who writes JavaScript on my team knows the coercion rules in JavaScript; otherwise they should probably be writing some transpiled language that lacks these features.


Non-zero does not imply `1'.

>The pattern is basically directly lifted from C, where there's thankfully no such thing as a boolean type.

There has been a boolean type in the current standard for C for longer than some of the younger people here have been alive.


Wow, I would never have known about stdbool. I have never seen it used (explicitly), even though it's been around since I was two years old. Thanks for bringing this to light! :- )

Nonetheless, bool or _Bool (aside from having implicit saturating arithmetic and assignment) is a one-bit integer type. It seems it mostly just formalizes the (implied, fictional) narrowing conversion involved in testing conditions, which is probably why I've not seen it used explicitly. The macros true and false seem to expand to 1 and 0 respectively.


That's because Boolean is a one-bit integer type. Whether you choose to call your 0s and 1s "false" and "true", correspondingly, doesn't change that.

Furthermore, from this perspective, a Boolean AND is just integer multiplication; Boolean OR is saturating addition; Boolean XOR is inequality; and Boolean IMP is saturating subtraction.


To be fair, I'd trade that for

    a += record.bool ? 1 : 0;
if I can have less awkward type coercions in return in a heartbeat.


Come on! Tongue in cheek

  a += !!record.bool;
There now. Happier?


This misses the point. !! stills returns a Boolean.


To be fair,

    let a = 0;
    for (const record of records) {
        if (record.bool){
          a += 1;
        }
    }
or

    ls.filter(x => x).length;
aren't that much harder to read. The second one probably doesn't do deforestation and would end up stupidly slow, though.


For the first one, would engines like v8 be smart enough to optimize it so it isn't wasting time on a pointless if-branch? (I'd imagine not, as it would be pretty hard for the engine to know that all the record.bool's are booleans.)




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: