Unifying logical operators

php.internals

Ryan

8 years ago
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

Walter Parker

8 years ago
On Mon, Jul 9, 2018 at 9:03 PM Ryan <iggyvolz@gmail.com> wrote:
> 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'); >
That is a matter of style, as I find $a = func() or die more clear that the version that uses || Not chaining stuff together is a third style. This feels like a Python PEP request. By that I mean that Python wants to have only one way to do any one task. Perl style is there’s more than one way to do it. PHP has been a mix of these styles. The big question I have is how much PHP code will break due to an enforced style requirement? Removing them for style seems like it would be a big BC break. Aliasing them might lead to more subtle bugs in legacy code.
> > 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 >
-- The greatest dangers to liberty lurk in insidious encroachment by men of zeal, well-meaning but without understanding. -- Justice Louis D. Brandeis

Rowan Collins

8 years ago
On 10 July 2018 at 04:02, Ryan <iggyvolz@gmail.com> wrote:
> > 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. >
As your own next example demonstrates, it does rely on the difference in precedence, because without it, you could only use this idiom after carefully checking that the left-hand side would be evaluated in one go, and probably using an extra set of parentheses.
> ($gdImage = @imagecreatetruecolor(120, 20)) || die('Cannot Initialize new
GD image stream'); This is less readable both because of the extra parentheses, and because the || operator is not as easily read as the English word "or". While I've not seen it used much in PHP code, the "do this or die" idiom is common in Perl (which also has post-fix "if" and "unless" modifiers, so those are a different feature again). IF there is sufficient harm in having the extra operators, I would say removal is the only option - making them behave as aliases for || etc would just lead to even more confusion when they *don't* work the same way as in Perl, and in earlier versions of PHP. I'm not 100% convinced by the harm, though. Finally, a note on the "xor" operator - your draft says that this is equivalent to "!=", but that is not the case, because both can operate on non-boolean values. Consider "1 != 2" (true) vs "1 xor 2" (false). I don't think I've ever had a use for logical xor in PHP code, but there isn't anything to confuse it with, so no reason to remove it. Regards,
-- Rowan Collins [IMSoP]

Christoph Becker

8 years ago
On 10.07.2018 at 11:01, Rowan Collins wrote:
> While I've not seen it used much in PHP code, the "do this or die" idiom is > common in Perl (which also has post-fix "if" and "unless" modifiers, so > those are a different feature again).
It seems to me the “do this or die” idiom at least has been very common in PHP. There may still be some occurences in the manual proper, and definitely there are occurences in user contributed notes.
> Finally, a note on the "xor" operator - your draft says that this is > equivalent to "!=", but that is not the case, because both can operate on > non-boolean values. Consider "1 != 2" (true) vs "1 xor 2" (false). I don't > think I've ever had a use for logical xor in PHP code, but there isn't > anything to confuse it with, so no reason to remove it.
“xor” is equivalent to ^ (sans the precedence).
-- Christoph M. Becker

Rowan Collins

8 years ago
On 10 July 2018 at 12:09, Christoph M. Becker <cmbecker69@gmx.de> wrote:
> > “xor” is equivalent to ^ (sans the precedence). >
No, that's a *bitwise* XOR, which is a completely different operation: var_dump(1 xor 2); // bool(false) var_dump(1 ^ 2); // int(3) A consistent logical XOR with the same precedence as || and && could perhaps be spelled ^^, but there is no such operator in PHP. Regards,
-- Rowan Collins [IMSoP]

Christoph Becker

8 years ago
On 10.07.2018 at 13:41, Rowan Collins wrote:
> On 10 July 2018 at 12:09, Christoph M. Becker <cmbecker69@gmx.de> wrote: > >> “xor” is equivalent to ^ (sans the precedence). > > No, that's a *bitwise* XOR, which is a completely different operation: > > var_dump(1 xor 2); // bool(false) > var_dump(1 ^ 2); // int(3) > > A consistent logical XOR with the same precedence as || and && could > perhaps be spelled ^^, but there is no such operator in PHP.
Thanks. I stand corrected!
-- Christoph M. Becker

Larry Garfield

8 years ago
On Tuesday, July 10, 2018 6:09:22 AM CDT Christoph M. Becker wrote:
> On 10.07.2018 at 11:01, Rowan Collins wrote: > > While I've not seen it used much in PHP code, the "do this or die" idiom > > is > > common in Perl (which also has post-fix "if" and "unless" modifiers, so > > those are a different feature again). > > It seems to me the “do this or die” idiom at least has been very common > in PHP. There may still be some occurences in the manual proper, and > definitely there are occurences in user contributed notes.
"do() or die()" code is/was very common in example code, tutorials, and other intro material because it means you don't need to think about error handling. I haven't seen it in actual production code in about 14 yeas, I think, and anyone who tried submitting it would get their patch rejected so hard it would make their head spin. It's a terrible pattern outside of fly-by-night tutorials. --Larry Garfield

Kalle Sommer Nielsen

8 years ago
Den tir. 10. jul. 2018 kl. 20.22 skrev Larry Garfield <larry@garfieldtech.com>:
> "do() or die()" code is/was very common in example code, tutorials, and other > intro material because it means you don't need to think about error handling.
I personally wanted to extend this syntax but I never got around to it to support: "do() or throw new Exception(...);", tho its just a code style over: "if(!do()){ throw new Exception(...); }"
-- regards, Kalle Sommer Nielsen kalle@php.net

Andrey Andreev

8 years ago
Hi, On Tue, Jul 10, 2018 at 9:37 PM, Kalle Sommer Nielsen <kalle@php.net> wrote:
> Den tir. 10. jul. 2018 kl. 20.22 skrev Larry Garfield <larry@garfieldtech.com>: >> "do() or die()" code is/was very common in example code, tutorials, and other >> intro material because it means you don't need to think about error handling. > > I personally wanted to extend this syntax but I never got around to it > to support: "do() or throw new Exception(...);", tho its just a code > style over: "if(!do()){ throw new Exception(...); }" >
I sometimes declare a closure that throws an exception to do just that. It's very convenient in short(ish) scripts. isset($foo) OR $foo = 'bar'; (and similar variations using empty() and/or &&) is another pattern I use often to set fallback values for empty or missing inputs. An eventual deprecation would make literally all of my code output entire screens of warnings. Cheers, Andrey.

David Rodrigues

8 years ago
I think that "or" could be removed if PHP could supports inline conditionals like: die() if !$connected; throw Exception() if fail(); $x = $y if (z() && w()); Or "when": die() when !$connected; It seems more clear than $connected or die(). Em ter, 10 de jul de 2018 às 15:59, Andrey Andreev <narf@devilix.net> escreveu:
> Hi, > > On Tue, Jul 10, 2018 at 9:37 PM, Kalle Sommer Nielsen <kalle@php.net> > wrote: > > Den tir. 10. jul. 2018 kl. 20.22 skrev Larry Garfield < > larry@garfieldtech.com>: > >> "do() or die()" code is/was very common in example code, tutorials, and > other > >> intro material because it means you don't need to think about error > handling. > > > > I personally wanted to extend this syntax but I never got around to it > > to support: "do() or throw new Exception(...);", tho its just a code > > style over: "if(!do()){ throw new Exception(...); }" > > > > I sometimes declare a closure that throws an exception to do just > that. It's very convenient in short(ish) scripts. > > isset($foo) OR $foo = 'bar'; (and similar variations using empty() > and/or &&) is another pattern I use often to set fallback values for > empty or missing inputs. > > An eventual deprecation would make literally all of my code output > entire screens of warnings. > > Cheers, > Andrey. > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php > >
-- David Rodrigues

Kalle Sommer Nielsen

8 years ago
Den tir. 10. jul. 2018 kl. 21.08 skrev David Rodrigues <david.proweb@gmail.com>:
> > I think that "or" could be removed if PHP could supports inline conditionals like: > > die() if !$connected; > throw Exception() if fail(); > $x = $y if (z() && w()); > > Or "when": die() when !$connected; > > It seems more clear than $connected or die().
I in fact find that more unreadable as you first got to dig through the error handling before you actually get to the logic that triggered it.
-- regards, Kalle Sommer Nielsen kalle@php.net

Rowan Collins

8 years ago
On 10/07/2018 20:11, Kalle Sommer Nielsen wrote:
> Den tir. 10. jul. 2018 kl. 21.08 skrev David Rodrigues <david.proweb@gmail.com>: >> I think that "or" could be removed if PHP could supports inline conditionals like: >> >> die() if !$connected; >> throw Exception() if fail(); >> $x = $y if (z() && w()); >> >> Or "when": die() when !$connected; >> >> It seems more clear than $connected or die(). > I in fact find that more unreadable as you first got to dig through > the error handling before you actually get to the logic that triggered > it.
A more readable syntax, if we were designing from scratch, might be to look at SmallTalk, where ifTrue and ifFalse are methods on the boolean class, so can appear post-fix after any boolean, giving you something like: $connected ifFalse: die(); Regards,
-- Rowan Collins [IMSoP]

Michael Morris

8 years ago
On Mon, Jul 9, 2018 at 10:03 PM Ryan <iggyvolz@gmail.com> wrote:
> 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. >
While having these behave they do is unfortunate, it is hardly the only one of PHP's quirks. Ever looked at the ramifications of loose typing with comparison? http://phpsadness.com/sad/52
> 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.
True, but that's still a lot of code to break. A *lot* of code. Far too much to consider changing this even at a major level I would think. PHP if anything, is too pragmatic a language for this change.

Rowan Collins

8 years ago
On 10/07/2018 20:38, Michael Morris wrote:
> While having these behave they do is unfortunate, it is hardly the only one > of PHP's quirks. Ever looked at the ramifications of loose typing with > comparison?http://phpsadness.com/sad/52
Eugh, I hate that site, and I hate that it's so widely linked as though it's some kind of well-researched resource rather than the ramblings of one rather opinionated developer. That's one of the more reasonable pages, but it's still an awful lot of words and spurious diagrams to say "coercing values means comparisons are intransitive in certain situations (most of which you'd never notice in every day use)". Regards,
-- Rowan Collins [IMSoP]

Ryan

8 years ago
On Tue, Jul 10, 2018 at 2:26 AM, Walter Parker <walterp@gmail.com> wrote:
> > That is a matter of style, as I find $a = func() or die more clear that > the version that uses || > > Not chaining stuff together is a third style. > > This feels like a Python PEP request. By that I mean that Python wants to > have only one way to do any one task. Perl style is there’s more than one > way to do it. > > PHP has been a mix of these styles. > > The big question I have is how much PHP code will break due to an enforced > style requirement?. >
As I said in the OP, out of the top 30 GitHub repositories (the first page on the API since I couldn't figure out how to get to the second), there was only one line that would require a change (and it was copy-pasted from the manual). Obviously there's no way to truly know how many times it's used in non-public code, but I'll expand my GitHub search and report back some more solid metrics. Removing them for style seems like it would be a big BC break. Aliasing
> them might lead to more subtle bugs in legacy code. >
PHP 7 code should never be blindly upgraded to PHP 8 (which is what this would target for actual changes, not just deprecation/notices). This would have to be clearly stated in the upgrade guide. On Tue, Jul 10, 2018 at 5:01 AM, Rowan Collins <rowan.collins@gmail.com> wrote:
> > > As your own next example demonstrates, it does rely on the difference in > precedence, because without it, you could only use this idiom after > carefully checking that the left-hand side would be evaluated in one go, > and probably using an extra set of parentheses. >
The defined or die idiom does not depend on precedence, because it doesn't contain an assignment operator. One could theoretically do $isDefined=defined("X") or die() - however that would be pointless as $isDefined would always be true.
> > ($gdImage = @imagecreatetruecolor(120, 20)) || die('Cannot Initialize > new GD image stream'); > > This is less readable both because of the extra parentheses, and because > the || operator is not as easily read as the English word "or". >
The readability issue is why I included the option to alias to or. I definitely agree that x() or die() looks better than x()||die().
> > While I've not seen it used much in PHP code, the "do this or die" idiom > is common in Perl (which also has post-fix "if" and "unless" modifiers, so > those are a different feature again). >
Forgive my lack of knowledge with perl, but it looks[1] like they only support a postfix if and postfix unless operators - which can serve the same purpose as PHP's and/or (x and y => y if x, x or y => y unless !x). However, I'm not aware of any language that uses and/or for this behaviour. I doubt there will be sufficient cause for confusion with perl as many languages have slightly different behaviours for and/or (and whether they use the text or symbolic versions). Lua and python use and/or, but don't convert the result to boolean and C{,#,++} use symbolic and convert the result to boolean. I don't know of a language that uses and/or in this way (unless I'm wrong about Perl) to denote a postfix operator.
> > IF there is sufficient harm in having the extra operators, I would say > removal is the only option - making them behave as aliases for || etc would > just lead to even more confusion when they *don't* work the same way as in > Perl, and in earlier versions of PHP. I'm not 100% convinced by the harm, > though. >
My thought for aliasing is that it may help with legacy code (if you're not relying on the return value, which is 99% of cases), as well as there being no symbolic equivalent for xor (as you state below it's not equivalent to != as I thought)
> > > Finally, a note on the "xor" operator - your draft says that this is > equivalent to "!=", but that is not the case, because both can operate on > non-boolean values. Consider "1 != 2" (true) vs "1 xor 2" (false). I don't > think I've ever had a use for logical xor in PHP code, but there isn't > anything to confuse it with, so no reason to remove it. >
Ah, my mistake. My only experience with xor was one class that I sat in on in the middle of the semester. It may be worth adding a symbolic representation of xor regardless. On Tue, Jul 10, 2018 at 2:37 PM, Kalle Sommer Nielsen <kalle@php.net> wrote:
> > I personally wanted to extend this syntax but I never got around to it > to support: "do() or throw new Exception(...);", tho its just a code > style over: "if(!do()){ throw new Exception(...); }" >
do() or throw doesn't actually work because throw is a language construct, not a function. $ php -r 'false or throw new Exception();' PHP Parse error: syntax error, unexpected 'throw' (T_THROW) in Command line code on line 1 I actually ran into this at work today writing a bootstrap function. I had a function that would return a class that would either give the path to a file in a subdirectory, or null if it didn't exist. I was attempting to call it like $file=self::findFile("subdirectory") and return $file; (continuing the loop if it didn't return). However, this isn't possible since return is a language construct. [1]: http://perl101.org/flow-control.html On Tue, Jul 10, 2018 at 2:58 PM, Andrey Andreev <narf@devilix.net> wrote:
> isset($foo) OR $foo = 'bar'; (and similar variations using empty() > and/or &&) is another pattern I use often to set fallback values for > empty or missing inputs. > > An eventual deprecation would make literally all of my code output > entire screens of warnings. >
$foo=$foo??"bar"; would work there. I could definitely see this being an issue if you weren't using isset (although a concrete example of that doesn't come to mind right away). On Tue, Jul 10, 2018 at 3:21 PM, Rowan Collins <rowan.collins@gmail.com> wrote:
> On 10/07/2018 20:11, Kalle Sommer Nielsen wrote: > >> Den tir. 10. jul. 2018 kl. 21.08 skrev David Rodrigues < >> david.proweb@gmail.com>: >> >>> I think that "or" could be removed if PHP could supports inline >>> conditionals like: >>> >>> die() if !$connected; >>> throw Exception() if fail(); >>> $x = $y if (z() && w()); >>> >>> Or "when": die() when !$connected; >>> >>> It seems more clear than $connected or die(). >>> >> I in fact find that more unreadable as you first got to dig through >> the error handling before you actually get to the logic that triggered >> it. >> > > > A more readable syntax, if we were designing from scratch, might be to > look at SmallTalk, where ifTrue and ifFalse are methods on the boolean > class, so can appear post-fix after any boolean, giving you something like: > > $connected ifFalse: die(); >
I hesitate to propose adding a new syntax to PHP, especially for something so rarely used it makes me question if it's truly necessary. If anything I would think we should prefer a syntax that we can point to other languages as examples (like the if/unless syntax from Ruby). It feels odd to clean up a rarely used operator by replacing it with fresh syntactical sugar. On Tue, Jul 10, 2018 at 3:38 PM, Michael Morris <tendoaki@gmail.com> wrote:
> > 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. > > > True, but that's still a lot of code to break. A *lot* of code. Far too > much to consider changing this even at a major level I would think. > > PHP if anything, is too pragmatic a language for this change
I don't understand what you mean by a lot of code to break - this line would be completely unaffected if the aliasing option was chosen. By the second line, I meant that PHP supports this behaviour in both the or and || operators.

Alice Wonder

8 years ago
On 07/10/2018 07:20 PM, Ryan wrote:
> On Tue, Jul 10, 2018 at 2:26 AM, Walter Parker <walterp@gmail.com> wrote: > >> >> That is a matter of style, as I find $a = func() or die more clear that >> the version that uses || >> >> Not chaining stuff together is a third style. >> >> This feels like a Python PEP request. By that I mean that Python wants to >> have only one way to do any one task. Perl style is there’s more than one >> way to do it. >> >> PHP has been a mix of these styles. >> >> The big question I have is how much PHP code will break due to an enforced >> style requirement?. >> > > As I said in the OP, out of the top 30 GitHub repositories (the first page > on the API since I couldn't figure out how to get to the second), there was > only one line that would require a change (and it was copy-pasted from the > manual). Obviously there's no way to truly know how many times it's used > in non-public code, but I'll expand my GitHub search and report back some > more solid metrics.
Using github may not be the most reliable method. Look at what is most popularly used in composer dependencies. For example, I know xor is used in PHP Codesniffer which while likely not often part of deployed code is very often a devel dependency. I think phpunit also uses xor and is also very popular. I use xor myself but my use is purely hobby (I have a pseudo-RNG written in PHP that can take any source of data, random or not, and pass it through a filter that makes it pass pRNG tests - showing that passing tests doesn't mean a random source is necessarily random enough for cryptography) Anyway as I believe you have already conceded, nuking xor would require many projects used a lot to have to change.

Walter Parker

8 years ago
On Tue, Jul 10, 2018 at 7:58 PM, Alice Wonder <alice@librelamp.com> wrote:
> On 07/10/2018 07:20 PM, Ryan wrote: > >> On Tue, Jul 10, 2018 at 2:26 AM, Walter Parker <walterp@gmail.com> wrote: >> >> >>> That is a matter of style, as I find $a = func() or die more clear that >>> the version that uses || >>> >>> Not chaining stuff together is a third style. >>> >>> This feels like a Python PEP request. By that I mean that Python wants to >>> have only one way to do any one task. Perl style is there’s more than one >>> way to do it. >>> >>> PHP has been a mix of these styles. >>> >>> The big question I have is how much PHP code will break due to an >>> enforced >>> style requirement?. >>> >>> >> As I said in the OP, out of the top 30 GitHub repositories (the first page >> on the API since I couldn't figure out how to get to the second), there >> was >> only one line that would require a change (and it was copy-pasted from the >> manual). Obviously there's no way to truly know how many times it's used >> in non-public code, but I'll expand my GitHub search and report back some >> more solid metrics. >> > > Using github may not be the most reliable method. > >
There are 67 Million repositories on GitHub, is picking the top 30 PHP projects a representative sample of PHP use across the Internet? 80% of web servers where the back end language was known had PHP according to a recent survey. Picking 30 popular open source projects might bias the results of what you think is going in PHP usage. Look at what is most popularly used in composer dependencies.
> > For example, I know xor is used in PHP Codesniffer which while likely not > often part of deployed code is very often a devel dependency. > > I think phpunit also uses xor and is also very popular. > > I use xor myself but my use is purely hobby (I have a pseudo-RNG written > in PHP that can take any source of data, random or not, and pass it through > a filter that makes it pass pRNG tests - showing that passing tests doesn't > mean a random source is necessarily random enough for cryptography) > > Anyway as I believe you have already conceded, nuking xor would require > many projects used a lot to have to change. > > > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php > >
-- The greatest dangers to liberty lurk in insidious encroachment by men of zeal, well-meaning but without understanding. -- Justice Louis D. Brandeis

Ryan

8 years ago
On Tue, Jul 10, 2018 at 10:58 PM, Alice Wonder <alice@librelamp.com> wrote:
> Using github may not be the most reliable method. >
> Look at what is most popularly used in composer dependencies.
Absolutely - but it's the first one that came to mind when thinking of "how to get popular repositories really quick". I'm sorting by stars, but I can definitely also check any dependencies if they aren't already in the list.
> > For example, I know xor is used in PHP Codesniffer which while likely not > often part of deployed code is very often a devel dependency. > > I think phpunit also uses xor and is also very popular. > > I use xor myself but my use is purely hobby (I have a pseudo-RNG written > in PHP that can take any source of data, random or not, and pass it through > a filter that makes it pass pRNG tests - showing that passing tests doesn't > mean a random source is necessarily random enough for cryptography) > > Anyway as I believe you have already conceded, nuking xor would require > many projects used a lot to have to change.
I'm absolutely not trying to take away behaviour with real use cases like xor. That's why I'm leaning more heavily on the aliasing side so it would break very little code. If the decision was made to remove the text operators (or whatever the proper name for and, or, and xor is), there would need to be a symbolic xor operator. On Tue, Jul 10, 2018 at 11:37 PM, Walter Parker <walterp@gmail.com> wrote:
> There are 67 Million repositories on GitHub, is picking the top 30 PHP > projects a representative sample of PHP use across the Internet? > 80% of web servers where the back end language was known had PHP according > to a recent survey. > Picking 30 popular open source projects might bias the results of what you > think is going in PHP usage.
Of course not - I'm working on expanding the search (right now to 300, and then I'll probably do 3,000 overnight) as we speak and I'll go as far as my hard drive (and patience, and GitHub API) will allow. I don't really know of a good way to get usage metrics for a token beyond "get some code using PHP and check for the token".

Andrey Andreev

8 years ago
Hi, On Wed, Jul 11, 2018 at 5:20 AM, Ryan <iggyvolz@gmail.com> wrote:
> On Tue, Jul 10, 2018 at 2:58 PM, Andrey Andreev <narf@devilix.net> wrote: > >> isset($foo) OR $foo = 'bar'; (and similar variations using empty() >> and/or &&) is another pattern I use often to set fallback values for >> empty or missing inputs. >> >> An eventual deprecation would make literally all of my code output >> entire screens of warnings. >> > > $foo=$foo??"bar"; would work there. I could definitely see this being an > issue if you weren't using isset (although a concrete example of that > doesn't come to mind right away). >
I'm very well aware of the alternatives, that's not the point. I and although not a majority, many others too would have to go and replace countless instances of OR usage, for no reason other than "it can be done another way". Aside from a few people asking what the difference is, in more than a decade with PHP, I've never seen a single person who's had a problem with the operators you want to deprecate. They're not a common cause for bugs even by a long shot, nor a common annoyance, so I fail to see the benefits of your proposal. Cheers, Andrey.

Rowan Collins

8 years ago
On 11 July 2018 at 03:20, Ryan <iggyvolz@gmail.com> wrote:
> > PHP 7 code should never be blindly upgraded to PHP 8 (which is what this > would target for actual changes, not just deprecation/notices). This would > have to be clearly stated in the upgrade guide. >
There's a big difference between "not blindly updating" and "having to run a static analysis tool and carefully read its results to stop your code having a subtly different behaviour". Introducing new errors is nearly always better than silently changing behaviour (this is the entire principle of run-time type checks, after all).
> On Tue, Jul 10, 2018 at 5:01 AM, Rowan Collins <rowan.collins@gmail.com> > wrote: > > As your own next example demonstrates, it does rely on the difference in > > precedence, because without it, you could only use this idiom after > > carefully checking that the left-hand side would be evaluated in one go, > > and probably using an extra set of parentheses. > > > > The defined or die idiom does not depend on precedence, because it doesn't > contain an assignment operator. One could theoretically do > $isDefined=defined("X") or die() - however that would be pointless as > $isDefined would always be true. >
Right, which is why I said your *next* example, which did use assignment. The point is that *reliably using the idiom* requires a specific precedence, so that you don't have to carefully vet which other operators are involved in the expression.
> > While I've not seen it used much in PHP code, the "do this or die" idiom > > is common in Perl (which also has post-fix "if" and "unless" modifiers, > so > > those are a different feature again). > > > > Forgive my lack of knowledge with perl, but it looks[1] like they only > support a postfix if and postfix unless operators - which can serve the > same purpose as PHP's and/or (x and y => y if x, x or y => y unless !x). >
Perhaps I worded that badly. I was saying two things: - The "do or die" idiom is extremely common in Perl. Just searching the documentation should be enough to convince you of that: https://duckduckgo.com/?q=site%3Aperldoc.perl.org+"or+die" - Perl *also* has post-fix if and unless operators, which you had mentioned in Ruby (Ruby inherited a lot from Perl). Clearly, people don't see these as a better replacement for the use of "or".
> My thought for aliasing is that it may help with legacy code (if you're not > relying on the return value, which is 99% of cases), as well as there being > no symbolic equivalent for xor (as you state below it's not equivalent to > != as I thought) >
Just to reiterate, I strongly feel that aliasing is not an option. If the aim is to reduce confusion, having the same code give different results in different PHP versions is a massive own goal.
> On Tue, Jul 10, 2018 at 2:37 PM, Kalle Sommer Nielsen <kalle@php.net> > wrote: > > > > > I personally wanted to extend this syntax but I never got around to it > > to support: "do() or throw new Exception(...);", tho its just a code > > style over: "if(!do()){ throw new Exception(...); }" > > > > do() or throw doesn't actually work because throw is a language construct, > not a function. >
Yes, hence "wanted to extend this syntax" - the suggestion is that this would be a useful feature to add, not one that already exists.
> > A more readable syntax, if we were designing from scratch, might be to > > look at SmallTalk, where ifTrue and ifFalse are methods on the boolean > > class, so can appear post-fix after any boolean, giving you something > like: > > > > $connected ifFalse: die(); > > > > I hesitate to propose adding a new syntax to PHP, especially for something > so rarely used it makes me question if it's truly necessary. If anything I > would think we should prefer a syntax that we can point to other languages > as examples (like the if/unless syntax from Ruby). It feels odd to clean > up a rarely used operator by replacing it with fresh syntactical sugar. >
I agree that adding new syntax is unnecessary for this, but since you keep mentioning the postfix if/unless which Ruby inherited from Perl, I thought I'd point to another language we could borrow syntax from, which is actually closer to the current idiom ("condition keyword action", not "action keyword condition"). Regards,
-- Rowan Collins [IMSoP]