Hello all! Longtime PHP user, first-time contributor to internals (sorry if I screw anything up)!
I'd like to propose either the deprecation (7.next - likely 7.4 at this point) and removal (8.0) of the T_LOGICAL_OR (or), T_LOGICAL_AND (and), and T_LOGICAL_XOR (xor) tokens, or aliasing them to ||, &&, and != respectively. The behaviours of the two sets of logical operators are very similar (it's incredibly unclear how $x or $y would differ from $x||$y). They perform almost identically except for the fact that the former set has a precedence lower that the assignment, null coalescing, and ternary operators[1]. The page on logical operators[2] states that the reason the two variations exist is that they "operate at different precedences" (which isn't a reason for existence, but rather a statement of differences). Example #1 on the logical operators page[2] gives an example of this difference: $e = false || true; // true $f = false or true; // false Because of the difference of precedence, the second line is evaluated as ($f = false) or true; In my mind (and in the mind of every programmer I've spoken to about this), this violates the principle of least astonishment[3]. The assignment operator is usually thought to be the lowest level of precedence other than parenthesis (as a typical statement would be "do some thing, then assign its value to this varible"). This[4] stackoverflow question sheds some light on the intent of the alternative operators - they are used for "control flow" in the style of Ruby's "unless" operator[5]: defined("SOME_CONSTANT") or die("SOME_CONSTANT was not defined"); However, this behaviour has nothing to do with the difference of precedence - rather this is due to short circuiting. The only difference between the two (unless there are interactions I'm not aware of with the ternary or null coalescing operator) is the precedence with the assignment operator, causing the return value to be assigned without respect to the conditional. I ran a quick (possibly imperfect) script on GitHub's top 30 repositories, and of the usages of the T_LOGICAL_* operators all but this one[6] operated equivalently to the symbolic ones: $gdImage = @imagecreatetruecolor(120, 20) or die('Cannot Initialize new GD image stream'); In this case, the result of imagecreatetruecolor is intended to be placed in $gdImage, or if it is falsey, die with an error. This could be rewritten as: ($gdImage = @imagecreatetruecolor(120, 20)) || die('Cannot Initialize new GD image stream'); Or, in my opinion, more cleanly: $gdImage = @imagecreatetruecolor(120, 20); if(!$gdImage) die('Cannot Initialize new GD image stream'); I've written a very rough draft RFC here[7] - and I would love feedback. If it's taken well I can put it up on the wiki. Thanks, Ryan "Iggy" Volz [1]: http://php.net/manual/en/language.operators.precedence.php [2]: http://php.net/manual/en/language.operators.logical.php [3]: https://en.wikipedia.org/wiki/Principle_of_least_astonishment [4]: https://stackoverflow.com/a/5998351 [5]: https://www.tutorialspoint.com/ruby/ruby_if_else.htm#Ruby%20unless%20modifier [6]: https://github.com/PHPOffice/PhpSpreadsheet/blob/aa5b0d0236c907fd8dba0883f3ceb97cc52e46ec/samples/Basic/25_In_memory_image.php#L24 - likely copied from http://php.net/manual/en/function.imagecreatetruecolor.php [7]: https://github.com/iggyvolz/Unifying-Operators-RFC