On Wed, Jun 26, 2019 at 12:39 PM Claude Pache <claude.pa...@gmail.com> wrote:
> > > > Le 26 juin 2019 à 11:36, Benjamin Morel <benjamin.mo...@gmail.com> a > écrit : > > > >> (...) could be the case depending on a declaration somewhere else in the > > source code. > >> That's the confusion Claude and I were talking about: You cannot be sure > > what a very simple line of code does. > > > > Oh, I see. You mean that only replacing some of the current results with > > TypeErrors would be acceptable; returning a different value would not. > > This makes a lot of sense, but once again prevents the language from > slowly > > moving towards something different (and better), leaving it stuck in its > > legacy forever. > > > > I'm starting to believe that a joint effort to fork PHP if the only way > out > > :( > > > > Ben > > > It would be something “different”, but not necessarily “better”. > > Programmers may intentionally rely on the current semantics when comparing > numeric strings, e.g. in the following cases: > * values that are grabbed from a database using a driver that returns only > strings (or nulls); > * values that are read from $_POST and that ultimately stems from some > HTML <input type="number"> element. > > ------- > > It was certainly a fundamental design error to have both implicit type > conversion and operators that did different things based on the type of > their operands. That leads to the infamous `"1" + 1 == 11` problem in > JavaScript, or the the "3" < "24" problem in PHP. That could have been > avoided in two ways: > * either by forbidding implicit conversion; > * or by using different operators for different types (as does Perl). > > Now, returning to the case of the comparison operators like `<` or `==`. > Instead of killing implicit conversion and redefining the meaning of those > operators in cases that are *not* just edge case, it may be preferable to > use the other approach: > > * in some strict mode, reserve `<`, `==` etc. for numeric comparison, and > throw a TypeError one of the operand is not numeric; > > * If we deem it worth, define a new operators for string comparison. > (Although I’m not really sure it is worth: we have `strcmp()` and `===` for > byte-to-byte comparison, and the Collator class for alphabetical sorting > that actually works in languages not restricted to unaccented latin > characters.) > > —Claude > > > Forbidding implicit type conversion completely is taking it to far. Some operators like string concatenation (`.`) can perform conversions just fine. The issue at hand is limited to operators that are affected by the value (not only the type) of the operands. Specifically: 1. When using numeric strings with relational operators. This includes statements like `"16" == "016"`. 2. When comparing two arrays, eg `[null] == [0]` and `[0] == ["foo"]`, or comparing two objects. 3. In a `switch` statement. -- 3. Whether a switch is or isn't affected by `strict_operators` should be determined via a secondary vote. 2. Concerning the `==` and `!=` with arrays and objects. There is currently a range of differences when compared to the effect of `===` and `!==`. To what extent is the typecasting intended? Some cases like `[0] == [false]` can be common. As such widening primitive conversion from bool to int might be a good idea (in general). Beyond that allowing cases like `[[]] == [false]` would undermine the purpose of this RFC as it allows seemingly self-contradicting statements to evaluate to true, like $a == $b && $a == $c && $b != $c with $a = [false]; $b = [0]; $c = [[]]; 1. The `strict_types` directives already require you to cast raw data from `$_GET`/`$_POST` or a database. In case using the directive would disallow strings, arrays, and objects as operands for relational operators (throwing a `TypeError`), would still require explicit casting. The difference is that when you forget to do that or copy the code from a code base where this isn't required, you'd always get a `TypeError`, rather than it giving a different result. I don't think a `TypeError` should not be thrown based on the value of an operand, only based on the type. Also. implicitly casting strings to numbers, but not casting other types (like arrays), is only making the logic of operators more complex and inconsistent. Disallowing relational operators `==`, `!=`, `<`, `>`, `<=`, `>=` and `<=>` for strings altogether, requiring the use of a function is an option. However, IMHO this is killing a fly with a cannon, as the problem is limited to "copy/pasted code for comparing numeric strings from a source file that doesn't use strict_operators to a file does use it". -- So, should a directive, declared at the top of the file, affect how the code in that file is executed? Afaics YES, that's exactly what it's for > The declare construct is used to set execution directives for a block of code. (https://www.php.net/declare)