Live data from Hacker News

JavaScript: The Curious Case of null >= 0

blog.campvanilla.com

31–40 of 152 posts

Re: JavaScript: The Curious Case of null >= 0

#31
post #11

Earlier quoted context omitted.

Okay. Find an equivalently surprising example in... Let's use the other poster's choice, python. I'll wait. Edit: didn't have to wait long, way to go Python! Maybe I'll just claim it probably has fewer of these types of bizarre idiosyncrasies? I hope it has fewer... I'm always baffled by JavaScript apologists... Look, your baby is ugly. We know it's ugly. You know it's ugly. But if we point out the problems, hey, may…

I find this behavior surprising: >>> d = {0: "int"} >>> d[False] = "bool" >>> d {0: 'bool'} >>> nan = float('nan') >>> d[nan] = 0 >>> d[nan] = 1 >>> d {0: 'bool', nan: 0, nan: 1} Yes, yes, it's because issubclass(bool, int) == True, and nan != nan, but weird. And if we include Python 2 you get the truly ridiculous: >>> dict() >> dict >> 0 >> 0 To compare e.g. a dictionary and set we compare the _names_ of the types!…

The `nan` thing is actually because `float('nan')` can (and does) return a new object (well, with a different ID) each time. So it's like going `d[object()] = 'a'; d[object()] = 'b'` and not retaining the objects for lookup.

> Personally I'd just make any comparison involving different types an error

As you point out, this is what Python 3 did for `None`. But it's been idiomatic to have 0 = False when languages didn't have `False`; so `bool(0) == False` makes sense, but also `sum(boolean for boolean in sequence)` works. So you could argue that for `True` and `False`, meaningful coercion is possible, and in reverse, if zero is false-y and everything else is truth-y (like in C), then that also makes sense. Imagine if you had to cast every number to a boolean explicitly! So I guess having `d[0] == d[False]` is the lesser of evils.

Re: JavaScript: The Curious Case of null >= 0

#32

Dynamic typing is a nightmare.

While I dislike dynamic typing in general, in this case the nightmare comes from aggressive and inconsistent coercions. You could have the same mayhem in a statically-typed language with poorly-considered implicit typecasts.

Re: JavaScript: The Curious Case of null >= 0

#33

Dynamic typing is a nightmare.

It's not so much dynamic typing, but a lack of typing. Dynamic typing means that type checks are made at runtime. e.g. in Ruby: irb> nil >= 0 NoMethodError: undefined method `>=' for nil:NilClass and Python 3: >>> None >= 0 TypeError: '>=' not supported between instances of 'NoneType' and 'int' Obviously JS (and Python 2!) get this wrong, but to be fair JS was designed in the 90s.

Someone else pointed out that Java has (or had?) a similar issue with comparing boxed Ints -- equality checks for object level equality while inequality compares the values.

Without explicit casting, the equality operator casts to a more general type (or rather, doesn't cast at all) than the inequality operator (which casts to numerics).

This happens anywhere you have weird coercion rules.

Re: JavaScript: The Curious Case of null >= 0

#34
post #26

Not to defend JavaScript too much, but I think the three examples seem reasonable when viewed in the right way, and I think it's hard for JavaScript to do much better with its existing design philosophy (dynamic typing and coercion rather than runtime errors to deal with type mismatches). >= and > are numerical operations, so both sides are interpreted as a number, and null is 0 when treated as a number. That means `…

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

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.

Re: JavaScript: The Curious Case of null >= 0

#35

Not to defend JavaScript too much, but I think the three examples seem reasonable when viewed in the right way, and I think it's hard for JavaScript to do much better with its existing design philosophy (dynamic typing and coercion rather than runtime errors to deal with type mismatches). >= and > are numerical operations, so both sides are interpreted as a number, and null is 0 when treated as a number. That means `…

Let me agree with you but then turn that on its head.

You've argued that having `null >= 0` is the best that JS could do while having a coercion-based semantics. And I agree: this confusing behavior may be the best you can possibly do with a coercion-based semantics. And it's not just this example, either. JavaScript is filled with gotchas, and a lot of them have to do with automatic coercion. For example, did you know there are number and string values x, y, and z, such that xBut if this is really the best you can do in the presence of automatic coercion, maybe that's an argument against coercion.

Re: JavaScript: The Curious Case of null >= 0

#36
post #26

Earlier quoted context omitted.

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

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'…

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.

Re: JavaScript: The Curious Case of null >= 0

#37
post #5

Did he seriously claim at the end that that made sense "mathematically"?

Yes. For X and Y being of the same type, defining the Define X X > Y : X X == Y: !(X X) X != Y: !(X == Y) X >= Y: !(X X That's why it's the only operator that needs to be defined for std::map/set (which are rb-trees) in C++ Now, if X and Y aren't the same type, the only thing you can expect to get out of the system is a cronenberg.

> X == Y: !(X X)

Only for totally ordered sets [1]. Floating-point numbers, for example, are not totally ordered, because !(NaN == NaN).

[1] https://en.wikipedia.org/wiki/Total_order

Re: JavaScript: The Curious Case of null >= 0

#38
Dynamic languages with implicit type conversions are designed to make the easy cases easy (think of JS operating on webpage input, where everything is initially a string; would it have the influence and popularity it does today, if lots of explicit conversions had to be written?), but as a side-effect, the hard cases can become perplexing.

I have no doubt those steps specified in the standard had plenty of thought put into them. It has to handle all the types, as well as those special cases of infinities, NaNs, and +/-0, such that the common cases make sense. However, I think a flowchart or other graphical means of illustrating those algorithms would be far easier to understand.

Re: JavaScript: The Curious Case of null >= 0

#39
post #36

Earlier quoted context omitted.

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'…

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.

Re: JavaScript: The Curious Case of null >= 0

#40
post #26

Not to defend JavaScript too much, but I think the three examples seem reasonable when viewed in the right way, and I think it's hard for JavaScript to do much better with its existing design philosophy (dynamic typing and coercion rather than runtime errors to deal with type mismatches). >= and > are numerical operations, so both sides are interpreted as a number, and null is 0 when treated as a number. That means `…

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

Be liberal in what you expect and precise in what you emit.
Post reply on HN