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, maybe the ECMA will update the language to fix some of the issues.
Meanwhile, being aware of them is often important in order to build correct, secure code.
And they're just entertaining.
So chill. Let's all laugh at how ugly JS is on a Saturday morning and enjoy ourselves a bit. Because when it comes to the JS ecosystem, if we can't laugh, we'd probably be crying...
>>> 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() < set()
True
>>> dict < set()
False
>>> 0 < dict
True
>>> 0 < 1j
TypeError: no ordering relation is defined for complex numbers
To compare e.g. a dictionary and set we compare the _names_ of the types! Except complex numbers, because they don't have an ordering. I actually have come across this as a bug in production.Personally I'd just make any comparison involving different types an error. That probably interacts poorly with subtyping, but it's a price I'm willing to pay.
> 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.
> "" = [] True
Which makes perfect sense if you know any Haskell, but looks like a JavaScript wat if you don't.
https://speakerdeck.com/alangpierce/python-puzzlers
Several of the examples from that talk have equivalents in JavaScript where JavaScript does better. I think pretty much any real-world language has lots of surprises like this that you need to get used to, although I certainly admit JavaScript (particularly JS type coercion) tends to have especially surprising behavior.
> I'll wait.
I don't write Python, but even so it took about 30 seconds, using the same area of the linked article as a starting point:
>>> 0 > None
True
At this point, I fully expect some attempt at a post-hoc rationalization for why Python's choice here is unimpeachable.In python 2, cross-type comparisons are strictly ordered. So:
>>> None == 0
False
>>> None < 0
True
>>> None <= 0
True
>>> None > 0
False
Completely consistent, no special cases, and if you sort() a list containing multiple types, it'll always come out in an unsurprising, consistent order.