Don't let it - he understands exactly how the types are being converted in order to make it appear that true == false.
This sort of thing happens in type conversion languages. You can either use === to stop conversion or you can understand how conversion works.
I'm not sure how the order of conversions is decided by PHP, but here's a brief explanation:
Compare "foo" to true. Convert the string "foo" to a boolean value. As it is desirable that a non-empty string evaluate to true, we will say they are "equal."
Compare "foo" to 0. Convert the string "foo" to a numeric value. As "foo" does not start with 0x it cannot be hex, and as it does not start with 0 it cannot be octal, so evaluate it as decimal - there are no numbers before the first letter so the string foo, when numerical, is 0.
Evaluate 0 to false. Well, that's just binary now isn't it? Of course false and 0 are equal!
The moral of the story, == is not "exactly equal" it is "relatively equal."
The problem with designing a language that does these sorts of implicit type conversions is that the "equality" operator violates the fundamental properties of equality. Since grade school mathematics we are all taught that equality is symmetric and transitive, and PHP's == operator is neither.
You can either use === to stop conversion or you can understand how conversion works.
It has been my experience that, to a first approximation, no-one fully understands how conversion works in such languages to the point of never getting it wrong in practice.
Of course we didn't know that would be the case when some of these languages were first created, but I think it is a compelling argument for making an actual-equality == operator the default in any new programming language design. There are enough plausible differences because of things like reference vs. value semantics already, without breaking basic intuitions about what comparisons mean as well.
> This sort of thing happens in type conversion languages. You can either use === to stop conversion or you can understand how conversion works.
You must admit that this is a lot of behavior to keep in mind.
Eg, there is no pattern like "try converting the value on the right to the type of the value on the left".
> Compare "foo" to 0. Convert the string "foo" to a numeric value.
I would expect this to convert 0 to "0" and fail. I suppose it's done this way because there's no way to represent a hexadecimal number except as a string.
> The moral of the story, == is not "exactly equal" it is "relatively equal."
The moral of the story for me would be "never use ==", if I were using PHP. I don't want to think about so many rules when trying to do a simple comparison.
FWIW, Ruby allows type conversion, but it generally must be explicit: `5 == "5"` is false; you must either do `5.to_s` or `"5".to_i` to compare, therefore nothing unexpected can happen. `if some_var` does "convert" to a boolean, but the rule is "nil and false are falsey, everything else is truthy", so again, not much to remember.
"Hard to mess up" is better than "easy to mess up", even if it's possible to avoid the mistake.
Sort of. 'NaN' is one of the IEEE 754 floating point constants, along with 'Inf' for infinity. They are numeric types, in that they can be returned via operations on numbers, such as dividing zero by zero or adding '-Inf' to 'Inf'. See https://en.wikipedia.org/wiki/NaN
I always understood that the 'isNaN()' function was required to check if a numeric variable is equal to 'NaN' directly, since normal equality cannot be used as there are multiple valid bitwise representations of 'NaN' in the standard - it is a float with an exponent of all ones and a non-zero fraction. However, 'isNaN()' now seems to have been co-opted into being used to check if a string is not a number, i.e. does not represent a numeric value, and in fact I believe this is now the documented description of the function in ECMAScript?