9 ms·
"This RFC fixes the very strange case in PHP where 0 == "foo" results in true. There are some other edge cases like that one, and this RFC fixes them." It's go
by overgard 6y ago
"This RFC fixes the very strange case in PHP where 0 == "foo" results in true. There are some other edge cases like that one, and this RFC fixes them."
It's good they fixed it I suppose, but yikes. As much as people say PHP has advanced from its fractal of awfulness days, a lot of those fixes are shocking if you come from other languages.
- neals 6y agoWhy does 0 == "foo"?
- tyingq 6y ago"If you compare a number with a string or the comparison involves numerical strings, then each string is converted to a number" And a string that doesn't look like a number at all is converted to 0. No, I'm not condoning this madness.
- coldtea 6y agoWell, in C you can cast any random set of bytes to an int, so there's that...
- overgard 6y agoSure but in C you usually do that explicitly, on purpose. Here it's almost certainly not what you wanted or expected.. Also, C is 20-30 years older and I don't think I've ever read anyone really compliment its type system in any way other than saying it's simple.
- andreygrehov 6y agoIf one doesn't know the language, they can write shitty code, regardless whether it's C or PHP. Any decent PHP programmer knows about the `===` operator that doesn't do any type juggling.
- tyingq 6y agoThis problem isnt really fixed with === per se. Converting strings to numbers is a common need, and the weird type conversation here is broken (and being fixed) for more than just implicit conversions in comparisons. The PHP team is calling it "saner numeric strings"...seems to indicate they agree.
- totony 6y ago"foo" is type casted into an int and, since it's not an int even when casted, it gets casted to a falsey 0. (int)"9" === 9 (int)"a" === 0 I assume this will cause backward incompatibility? I could see people relying on this instead of is_numeric. Not sure I like this change, since it introduces multiple ways of type casting (and therefore complexity). Before, it was obscure but simple, now, it'd be both obscure and not simple. EDIT: It will cause backward incompatibility https://wiki.php.net/rfc/string_to_number_comparison https://wiki.php.net/rfc/string_to_number_comparison I'm surprised this was 44 against 1 in the vote. Seems like it's very likely to cause issues. IMO they should just implement a "strict comparison" mode, where comparing different types throws a runtime exception. Or just deprecate "==" for "===".
- coldtea 6y ago>I'm surprised this was 44 against 1 in the vote. Seems like it's very likely to cause issues. On the other hand, seems very much like the kind of crap that you're better to rip the band-aid and fix, than to keep for an eternity lest the fix causes issues... >Or just deprecate "==" for "===". As if this would cause less issues?
- totony 6y agoAutomatic type conversion is prone to errors. Either they acknowledge that and force strict comparison (or add a way to do that), or they ignore and thus their change has no real effect, since mistakes will still happen with the new scheme. >As if this would cause less issues? Causing issues isn't the problem. Transparently breaking code is. Deprecating would give time for people to adapt their code and would warn them about the downsides or loose type conversion. Changing the semantics of loose comparison will make static analysis and finding potential issues way harder (and may post-pone finding the problems it introduces to years down the line). Adding a mode that warns/throws when encountering loose comparison would both make current code still work, and warn users of potential issues.
- rectang 6y ago> you're better to rip the band-aid Not for silent failure. This soft of change means that tons of systems will fail in unexpected ways in unexpected places, and often people will never know about it. It's a security nightmare. Ripping the band-aid off is much more compelling when it will result in an exception. Silent failure, though. Ugh, if you actually care about writing reliable software, it's the worst.
- erik_seaberg 6y agoIt's a shame PHP borrowed so much from Perl but not separate "eq" and "==" operators that coerce to string and number before comparing. I want always one or always the other, not both unpredictably.
- jcfields 6y agoPHP half-copied Perl a lot. Another example is implementing arrays and hashes, but not as separate types. So you have odd behavior like the array sort functions sorting values but not renumbering keys because there's no distinction between an array and a map. Or copying Perl's string interpolation and concatenation operator but not its regular expression literals, so writing regexes in PHP requires an extra layer of escape sequences.
- cutler 6y agoI'm not aware of any extra layer of escape sequences required in PHP compared with Perl. Could you elaborate?
- jcfields 6y agoPHP requires escaping quotes and literal backslashes (i.e., backslashes not used for metacharacters or escaping other characters). For many cases, it doesn't affect anything, but it can turn into a bit of a nightmare if you're matching anything involving backslashes since you need four backslashes to match one literal backslash. Perl's regular expression literals are also nicer for things like splitting a long expression over multiple lines.
- cutler 6y agoI thought preg_quote() took care of that just like quotemeta in Perl?
- qalmakka 6y agoYeah, that's a real shame. I wrote lots of Perl and while it requires a bit of experience, I almost never incurred in issues such as those we see in PHP and JS. The fact Perl is also quite strict in you specify if the variable is hash, array or scalar also helps a lot, and IMHO the concept that it's the operator, not the operand that determines the type of the arguments is very powerful.
- kilburn 6y agoMost (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 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: Python: https://github.com/cosmologicon/pywat https://github.com/cosmologicon/pywat Javascript: https://loomcom.com/blog/0097_the_wats_of_javascript.html https://loomcom.com/blog/0097_the_wats_of_javascript.html Ruby: https://idiosyncratic-ruby.com/29-limitations-of-language.html https://idiosyncratic-ruby.com/29-limitations-of-language.ht...
- akiselev 6y agoThe 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 :)
- jorams 6y agoIt'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.)
- xapata 6y agoPython may have Wats, but C has Nasal Demons. https://en.m.wikipedia.org/wiki/Undefined_behavior#Examples_in_C_and_C++ https://en.m.wikipedia.org/wiki/Undefined_behavior#Examples_...
- paul_f 6y agoYes, maybe, but who would write that? Seems an arbitrary example used to denigrate weak typed languages in general. Not sure what is bering tested there, but easy enough to do this: if (is_numeric($foo) and !intval($foo)) {
- combatentropy 6y agoShould a string, when converted to an integer, become 1, not 0? (Unless it is a string of only digits, like "567". Then it should become 567.) (bool) 'x' // true (int) true // 1 If a string is truthy in a boolean situation, shouldn't it also be truthy in a numeric one? The types form a hierarchy in my mind, from simple to complex: from boolean to integer, to float, to string, to compound types like arrays and objects. It seems like values should cast up and down the chain uniformly.
- darthrupert 6y agoThese are easy questions. 1. If you convert a string which has non-numbers to an integer, an error is raised 2. Truthiness should not exist as a concept. Just booleans and expressions that evaluate to booleans. PHP's backwards compatibilty promise makes these more difficult questions, of course.
- pavlov 6y agoEasy questions but not obvious answers. What kind of error to raise? Do you return a NaN? Throw an exception? Both have their uses.
- darthrupert 6y agoThrow a standard exception. E.g. python calls it a ValueError. Returing NaN is clearly wrong design.
- Erlich_Bachman 6y ago> 2. Truthiness should not exist as a concept. Meh, it's actually quite useful in many situations.
- ehnto 6y agoIt's a good thing all other languages are perfect and have always been perfect, otherwise the rest of the community would have no pedestal to stand upon.
- tonyedgecombe 6y agoNobody is saying other languages are perfect. These are particularly egregious mistakes though.
- rawoke083600 6y agoOh please !!
- ehnto 6y agoIt was a consequence of type conversion in a loosely typed language. There are consequences to loose typing, one of them is edge cases. PHP also has strict typing capabilities. If you need strict typing, then use it, it's right there for you. My criticism isn't the valid criticisms of PHP, it's that no matter how much progress the language makes people are quick to find reasons to be dismissive. The language is good, people do good work with it. Lots of good work. How Javascript became the golden child in a community that can't forgive PHP is beyond me.
- pdimitar 6y ago> My criticism isn't the valid criticisms of PHP, it's that no matter how much progress the language makes people are quick to find reasons to be dismissive. It's perfectly valid to be dismissive of PHP and you should recognize that. Main reason: there's a metric ton of PHP 5.X websites out there who are never going to be upgraded. That alone is a reason enough to distrust PHP. If the community makes a concerted effort to introduce automated upgrades of legacy PHP codebases to the newer (supposedly better) versions then I personally would become a fan. Everybody can tout the newest and greatest. Working with -- and improving -- the legacy stuff is what earns the respect of many, myself included. (Disclaimer: not a JS dev. You seem to imply some kind of irony that JS devs mock PHP but this is not the case with me at least.)
- volume 6y agoShould it be shocking? It's another language that has it's own history and culture. It evolved it's own way.
- Ndymium 6y agoSeems like this still doesn't fix the infamous "1E1" == "010", which I guess can't be fixed without breaking a lot of old code and assumptions.
- Erlich_Bachman 6y agoIn reality, if you know what you are doing, you would never compare like that (0 == "foo"). What would be the use case? If you on the other hand don't know what you are doing, you are going to shoot yourself in the foot in one way or another. If you really have some dynamic type situation and you for some legitimate reason don't know if your variable is going to be an int or a string, you would just compare using the === operator, which is a standard and well-known tool and does not have this issue.
- occamrazor 6y ago> What would be the use case? Reading data from an excel sheet. A1 is “foo”, A2 is blank. B1 is =A1, which evaluates to “foo”, and B2 is =A2, which evaluates to 0. If you want to aggregate according to column B, you have to compare 0 and “foo”.
- Erlich_Bachman 6y agoYou have an excel sheet with various unknown data types which can be a string, a number or a formula that needs evaluation? And you don't check types of variables before comparing them? In that case I would argue that you fall into the category "not know what you are doing", because checking the type would be the first needed thing. That is the very first situation in which it is needed in fact...
- overgard 6y agoI could see this coming up in a pretty straightforward way actually. I used to have a coworker that would always write his conditions backwards, so like if(false == something) {} In this case it's a semi-obscure C programming style to avoid accidentally using = in an if statement. (I think it's silly, but a decent number of people do it). So I could easily see a case in PHP where someone writes... if(0 == $foo) and $foo usually holds a numerical string, but maybe a user entered "" there and now it's cast to 0 and maybe that code path shouldn't be taken.
- qalmakka 6y agoI think that the big mistake PHP and JS made was to loosely pick their weak typing from Perl while trying to look too much like Java. Perl has different operators for numeric and string equality, so you know that `$a == "3"` would convert both its arguments to number and then compare them, while `$a eq "3"` would convert them both as strings and run a character comparison on them. Using == for both was kind of asking for people to get confused and mess up, IMHO.
- zeroimpl 6y agoI’ve never used Perl but I periodically mistake eq and = in bash scripts. It’s quite annoying since there’s no obvious indication that one is for numbers and one is for strings.
- qalmakka 6y agoThere's no obvious indication what the standard C function void (*signal(int sig, void (*func)(int)))(int) means; if you don't know C it's plain gibberish, impossible to fully understand. Everything in computers (and I may say, more in general in life) is based on assumptions made on knowledge we implicitly have. After a while, writing eq or == becomes natural and you stop mixing them up. These kinds of errors are frequent when you don't use something daily; for instance, after more than a decade I still keep forgetting Powershell's syntax because I don't use it often and when I do, I tend to do basic things.