Most (non-strongly-typed?) languages have weird edge cases of this sort. There's a very funny presentation by Gary Bernhard highlighting some of these for Ruby/Javascript: https://www.destroyallsoftware.com/talks/wat
If you look hard enough, you'll probably find some site that shows surprising behaviors of your favorite language. Examples:
The issue is coercion sanity - not that PHP or JS are sane by any other standard to begin with. You can do `0 == "0"` in Javascript (try it now in the devtools console) and it'll coerce the right hand based on the left hand using parseInt/parseFloat, just like PHP. What it won't do is parse the string "foo" as a zero, which is insane even by Javascript standards.
`parseFloat("foo") == parseFloat("foo")` and `parseInt("foo") == parseInt("foo")` in Javascript evaluate to false which is the sane thing to do. `NaN != NaN` is part of the IEEE 754 floating point standard, which predates every single one of the languages you mentioned.
We're all competing in the olympics of suffering, so none of us should be promoting this shit :)
It's important to note here that PHP is converting to an integer, while JS is converting to a double. Integers don't have NaN as a concept. JS doesn't have integers, but if it did it would probably make the same kind of mistake. (This is a guess of course, but a reasonable one given the other insane conversions it does.)
jshell> Long a = 12l; Long b = 12l;
a ==> 12
b ==> 12
jshell> a == b
$3 ==> true
jshell> a = 54321l; b = 54321l;
a ==> 54321
b ==> 54321
jshell> a == b
$6 ==> false
`Long` is a boxed (reference) type, but small numbers are interned so you get the same reference when boxing a primitive value. Larger numbers aren't interned, so you get fresh boxes.
Reference comparison it is with a twist: the jvm caches the most common integers. You'll get the same object from -128 to +127 when implicitly assigning value. This is part of the spec, and can be set to a larger pool with -XX:AutoBoxCacheMax (but cannot be turned off).
If you explicitly ask for a new object (Long a = new Long(123l);) you will get a new object and the comparison will fail as expected.
The moral of the story is to always use .equals().
I love the "Wat" talk. I wrote a blog a few years ago where I attempted to dig into the JavaScript cases Gary's cites and figure out what is actually happening.
Yes. You have a list of floats and you want to add n to the n-th element. Then n is both an integer (when indexing the list) and a float (when adding).
Of course the language can require an explicit cast, but in most cases it goes against the intuitiveness and simplicity that dynamic languages want to achieve.
I think it is good and should be condoned. Sometimes having simple rules with the occasionally strange outcome is better than having a complicated set of rules to achieve a simple set of outcomes.
If you look hard enough, you'll probably find some site that shows surprising behaviors of your favorite language. Examples:
Python: https://github.com/cosmologicon/pywat
Javascript: https://loomcom.com/blog/0097_the_wats_of_javascript.html
Ruby: https://idiosyncratic-ruby.com/29-limitations-of-language.ht...